@drift-labs/sdk 0.2.0-master.25 → 0.2.0-master.26

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.
Files changed (184) hide show
  1. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +13 -13
  2. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +27 -27
  3. package/lib/accounts/types.d.ts +8 -9
  4. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +14 -14
  5. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +35 -34
  6. package/lib/addresses/pda.d.ts +7 -6
  7. package/lib/addresses/pda.js +31 -27
  8. package/lib/admin.d.ts +9 -6
  9. package/lib/admin.js +83 -42
  10. package/lib/clearingHouse.d.ts +69 -42
  11. package/lib/clearingHouse.js +753 -277
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +16 -16
  14. package/lib/clearingHouseUser.js +139 -119
  15. package/lib/config.d.ts +7 -7
  16. package/lib/config.js +20 -20
  17. package/lib/constants/numericConstants.d.ts +12 -12
  18. package/lib/constants/numericConstants.js +13 -13
  19. package/lib/constants/{markets.d.ts → perpMarkets.d.ts} +5 -5
  20. package/{src/constants/markets.js → lib/constants/perpMarkets.js} +4 -4
  21. package/lib/constants/{banks.d.ts → spotMarkets.d.ts} +6 -6
  22. package/lib/constants/{banks.js → spotMarkets.js} +16 -16
  23. package/lib/events/types.d.ts +2 -1
  24. package/lib/events/types.js +1 -0
  25. package/lib/examples/makeTradeExample.js +7 -7
  26. package/lib/idl/clearing_house.json +1008 -279
  27. package/lib/index.d.ts +5 -3
  28. package/lib/index.js +5 -3
  29. package/lib/math/amm.d.ts +2 -2
  30. package/lib/math/amm.js +1 -1
  31. package/lib/math/funding.d.ts +6 -6
  32. package/lib/math/funding.js +2 -1
  33. package/lib/math/margin.d.ts +4 -4
  34. package/lib/math/margin.js +18 -11
  35. package/lib/math/market.d.ts +10 -9
  36. package/lib/math/market.js +29 -6
  37. package/lib/math/oracles.d.ts +2 -1
  38. package/lib/math/oracles.js +11 -1
  39. package/lib/math/orders.d.ts +5 -5
  40. package/lib/math/position.d.ts +13 -13
  41. package/lib/math/position.js +19 -19
  42. package/lib/math/spotBalance.d.ts +19 -0
  43. package/lib/math/spotBalance.js +176 -0
  44. package/lib/math/spotMarket.d.ts +4 -0
  45. package/lib/math/spotMarket.js +8 -0
  46. package/lib/math/spotPosition.d.ts +2 -0
  47. package/lib/math/spotPosition.js +8 -0
  48. package/lib/math/state.js +2 -2
  49. package/lib/math/trade.d.ts +4 -4
  50. package/lib/orderParams.d.ts +4 -4
  51. package/lib/orderParams.js +12 -4
  52. package/lib/serum/serumSubscriber.d.ts +23 -0
  53. package/lib/serum/serumSubscriber.js +41 -0
  54. package/lib/serum/types.d.ts +11 -0
  55. package/lib/serum/types.js +2 -0
  56. package/lib/tx/retryTxSender.d.ts +1 -1
  57. package/lib/tx/retryTxSender.js +4 -2
  58. package/lib/tx/types.d.ts +1 -1
  59. package/lib/types.d.ts +123 -33
  60. package/lib/types.js +31 -9
  61. package/my-script/.env +7 -0
  62. package/my-script/getUserStats.ts +106 -0
  63. package/my-script/multiConnections.ts +119 -0
  64. package/my-script/test-regex.ts +11 -0
  65. package/my-script/utils.ts +52 -0
  66. package/package.json +1 -1
  67. package/src/accounts/bulkAccountLoader.js +249 -0
  68. package/src/accounts/bulkUserStatsSubscription.js +75 -0
  69. package/src/accounts/bulkUserSubscription.js +75 -0
  70. package/src/accounts/fetch.js +92 -0
  71. package/src/accounts/pollingClearingHouseAccountSubscriber.js +465 -0
  72. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +38 -38
  73. package/src/accounts/pollingOracleSubscriber.js +156 -0
  74. package/src/accounts/pollingTokenAccountSubscriber.js +141 -0
  75. package/src/accounts/pollingUserAccountSubscriber.js +208 -0
  76. package/src/accounts/pollingUserStatsAccountSubscriber.js +208 -0
  77. package/src/accounts/types.js +28 -0
  78. package/src/accounts/types.ts +11 -9
  79. package/src/accounts/utils.js +7 -0
  80. package/src/accounts/webSocketAccountSubscriber.js +138 -0
  81. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +433 -0
  82. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +59 -52
  83. package/src/accounts/webSocketUserAccountSubscriber.js +113 -0
  84. package/src/accounts/webSocketUserStatsAccountSubsriber.js +113 -0
  85. package/src/addresses/pda.js +186 -0
  86. package/src/addresses/pda.ts +49 -44
  87. package/src/admin.js +1284 -0
  88. package/src/admin.ts +140 -47
  89. package/src/assert/assert.js +1 -1
  90. package/src/clearingHouse.js +3433 -0
  91. package/src/clearingHouse.ts +1083 -378
  92. package/src/clearingHouseConfig.js +2 -0
  93. package/src/clearingHouseConfig.ts +2 -2
  94. package/src/clearingHouseUser.js +874 -0
  95. package/src/clearingHouseUser.ts +232 -168
  96. package/src/clearingHouseUserConfig.js +2 -0
  97. package/src/clearingHouseUserStats.js +115 -0
  98. package/src/clearingHouseUserStatsConfig.js +2 -0
  99. package/src/config.js +80 -0
  100. package/src/config.ts +29 -29
  101. package/src/constants/numericConstants.js +18 -11
  102. package/src/constants/numericConstants.ts +17 -15
  103. package/{lib/constants/markets.js → src/constants/perpMarkets.js} +11 -11
  104. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  105. package/src/constants/spotMarkets.js +51 -0
  106. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  107. package/src/events/eventList.js +66 -23
  108. package/src/events/eventSubscriber.js +202 -0
  109. package/src/events/fetchLogs.js +117 -0
  110. package/src/events/pollingLogProvider.js +113 -0
  111. package/src/events/sort.js +41 -0
  112. package/src/events/txEventCache.js +22 -19
  113. package/src/events/types.js +25 -0
  114. package/src/events/types.ts +3 -0
  115. package/src/events/webSocketLogProvider.js +76 -0
  116. package/src/examples/makeTradeExample.ts +10 -8
  117. package/src/factory/bigNum.js +183 -180
  118. package/src/factory/oracleClient.js +9 -9
  119. package/src/idl/clearing_house.json +1008 -279
  120. package/src/index.js +75 -0
  121. package/src/index.ts +5 -3
  122. package/src/math/amm.js +422 -0
  123. package/src/math/amm.ts +6 -3
  124. package/src/math/auction.js +10 -10
  125. package/src/math/conversion.js +4 -3
  126. package/src/math/funding.js +223 -175
  127. package/src/math/funding.ts +7 -7
  128. package/src/math/insurance.js +27 -0
  129. package/src/math/margin.js +77 -0
  130. package/src/math/margin.ts +34 -23
  131. package/src/math/market.js +105 -0
  132. package/src/math/market.ts +71 -19
  133. package/src/math/oracles.js +40 -10
  134. package/src/math/oracles.ts +18 -1
  135. package/src/math/orders.js +153 -0
  136. package/src/math/orders.ts +5 -5
  137. package/src/math/position.js +172 -0
  138. package/src/math/position.ts +31 -31
  139. package/src/math/repeg.js +40 -40
  140. package/src/math/spotBalance.js +176 -0
  141. package/src/math/spotBalance.ts +290 -0
  142. package/src/math/spotMarket.js +8 -0
  143. package/src/math/spotMarket.ts +9 -0
  144. package/src/math/spotPosition.js +8 -0
  145. package/src/math/spotPosition.ts +6 -0
  146. package/src/math/state.ts +2 -2
  147. package/src/math/trade.js +81 -74
  148. package/src/math/trade.ts +4 -4
  149. package/src/math/utils.js +8 -7
  150. package/src/oracles/oracleClientCache.js +10 -9
  151. package/src/oracles/pythClient.js +52 -17
  152. package/src/oracles/quoteAssetOracleClient.js +44 -13
  153. package/src/oracles/switchboardClient.js +69 -37
  154. package/src/oracles/types.js +1 -1
  155. package/src/orderParams.js +14 -6
  156. package/src/orderParams.ts +16 -8
  157. package/src/serum/serumSubscriber.js +102 -0
  158. package/src/serum/serumSubscriber.ts +80 -0
  159. package/src/serum/types.js +2 -0
  160. package/src/serum/types.ts +13 -0
  161. package/src/slot/SlotSubscriber.js +67 -20
  162. package/src/token/index.js +4 -4
  163. package/src/tokenFaucet.js +288 -154
  164. package/src/tx/retryTxSender.js +280 -0
  165. package/src/tx/retryTxSender.ts +5 -2
  166. package/src/tx/types.js +1 -1
  167. package/src/tx/types.ts +2 -1
  168. package/src/tx/utils.js +7 -6
  169. package/src/types.js +216 -0
  170. package/src/types.ts +110 -33
  171. package/src/userName.js +5 -5
  172. package/src/util/computeUnits.js +46 -11
  173. package/src/util/promiseTimeout.js +5 -5
  174. package/src/util/tps.js +46 -12
  175. package/src/wallet.js +55 -18
  176. package/lib/math/bankBalance.d.ts +0 -15
  177. package/lib/math/bankBalance.js +0 -150
  178. package/src/addresses/marketAddresses.js +0 -26
  179. package/src/constants/banks.js +0 -42
  180. package/src/examples/makeTradeExample.js +0 -80
  181. package/src/math/bankBalance.ts +0 -258
  182. package/src/math/state.js +0 -15
  183. package/src/math/utils.js.map +0 -1
  184. package/src/util/getTokenAddress.js +0 -9
@@ -5,17 +5,19 @@ import {
5
5
  IWallet,
6
6
  PositionDirection,
7
7
  UserAccount,
8
- MarketAccount,
8
+ PerpMarketAccount,
9
9
  OrderParams,
10
10
  Order,
11
- BankAccount,
12
- UserBankBalance,
11
+ SpotMarketAccount,
12
+ SpotPosition,
13
13
  MakerInfo,
14
14
  TakerInfo,
15
15
  OptionalOrderParams,
16
16
  DefaultOrderParams,
17
17
  OrderType,
18
18
  ReferrerInfo,
19
+ MarketType,
20
+ SerumV3FulfillmentConfigAccount,
19
21
  } from './types';
20
22
  import * as anchor from '@project-serum/anchor';
21
23
  import clearingHouseIDL from './idl/clearing_house.json';
@@ -43,6 +45,8 @@ import {
43
45
  getClearingHouseStateAccountPublicKey,
44
46
  getInsuranceFundStakeAccountPublicKey,
45
47
  getMarketPublicKey,
48
+ getSerumFulfillmentConfigPublicKey,
49
+ getSerumSignerPublicKey,
46
50
  getUserAccountPublicKey,
47
51
  getUserAccountPublicKeySync,
48
52
  getUserStatsAccountPublicKey,
@@ -56,11 +60,11 @@ import { TxSender } from './tx/types';
56
60
  import { wrapInTx } from './tx/utils';
57
61
  import {
58
62
  ONE,
59
- QUOTE_ASSET_BANK_INDEX,
63
+ QUOTE_SPOT_MARKET_INDEX,
60
64
  ZERO,
61
65
  } from './constants/numericConstants';
62
66
  import { findDirectionToClose, positionIsAvailable } from './math/position';
63
- import { getTokenAmount } from './math/bankBalance';
67
+ import { getTokenAmount } from './math/spotBalance';
64
68
  import { DEFAULT_USER_NAME, encodeName } from './userName';
65
69
  import { OraclePriceData } from './oracles/types';
66
70
  import { ClearingHouseConfig } from './clearingHouseConfig';
@@ -69,9 +73,10 @@ import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketCle
69
73
  import { RetryTxSender } from './tx/retryTxSender';
70
74
  import { ClearingHouseUser } from './clearingHouseUser';
71
75
  import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
72
- import { getMarketsBanksAndOraclesForSubscription } from './config';
73
- import { WRAPPED_SOL_MINT } from './constants/banks';
76
+ import { getMarketsAndOraclesForSubscription } from './config';
77
+ import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
74
78
  import { ClearingHouseUserStats } from './clearingHouseUserStats';
79
+ import { isSpotPositionAvailable } from './math/spotPosition';
75
80
 
76
81
  /**
77
82
  * # ClearingHouse
@@ -139,17 +144,21 @@ export class ClearingHouse {
139
144
  });
140
145
  }
141
146
 
142
- let marketIndexes = config.marketIndexes;
143
- let bankIndexes = config.bankIndexes;
147
+ let perpMarketIndexes = config.perpMarketIndexes;
148
+ let spotMarketIndexes = config.spotMarketIndexes;
144
149
  let oracleInfos = config.oracleInfos;
145
150
  if (config.env) {
146
151
  const {
147
- marketIndexes: envMarketIndexes,
148
- bankIndexes: envBankIndexes,
152
+ perpMarketIndexes: envPerpMarketIndexes,
153
+ spotMarketIndexes: envSpotMarketIndexes,
149
154
  oracleInfos: envOralceInfos,
150
- } = getMarketsBanksAndOraclesForSubscription(config.env);
151
- marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
152
- bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
155
+ } = getMarketsAndOraclesForSubscription(config.env);
156
+ perpMarketIndexes = perpMarketIndexes
157
+ ? perpMarketIndexes
158
+ : envPerpMarketIndexes;
159
+ spotMarketIndexes = spotMarketIndexes
160
+ ? spotMarketIndexes
161
+ : envSpotMarketIndexes;
153
162
  oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
154
163
  }
155
164
 
@@ -157,15 +166,15 @@ export class ClearingHouse {
157
166
  this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
158
167
  this.program,
159
168
  config.accountSubscription.accountLoader,
160
- marketIndexes ?? [],
161
- bankIndexes ?? [],
169
+ perpMarketIndexes ?? [],
170
+ spotMarketIndexes ?? [],
162
171
  oracleInfos ?? []
163
172
  );
164
173
  } else {
165
174
  this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
166
175
  this.program,
167
- config.marketIndexes ?? [],
168
- config.bankIndexes ?? [],
176
+ config.perpMarketIndexes ?? [],
177
+ config.spotMarketIndexes ?? [],
169
178
  config.oracleInfos ?? []
170
179
  );
171
180
  }
@@ -276,25 +285,30 @@ export class ClearingHouse {
276
285
  return this.accountSubscriber.getStateAccountAndSlot().data;
277
286
  }
278
287
 
279
- public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
288
+ public getPerpMarketAccount(
289
+ marketIndex: BN | number
290
+ ): PerpMarketAccount | undefined {
280
291
  marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
281
292
  return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
282
293
  }
283
294
 
284
- public getMarketAccounts(): MarketAccount[] {
295
+ public getPerpMarketAccounts(): PerpMarketAccount[] {
285
296
  return this.accountSubscriber
286
297
  .getMarketAccountsAndSlots()
287
298
  .map((value) => value.data);
288
299
  }
289
300
 
290
- public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
291
- bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
292
- return this.accountSubscriber.getBankAccountAndSlot(bankIndex).data;
301
+ public getSpotMarketAccount(
302
+ marketIndex: BN | number
303
+ ): SpotMarketAccount | undefined {
304
+ marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
305
+ return this.accountSubscriber.getSpotMarketAccountAndSlot(marketIndex).data;
293
306
  }
294
307
 
295
- public getQuoteAssetBankAccount(): BankAccount {
296
- return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
297
- .data;
308
+ public getQuoteSpotMarketAccount(): SpotMarketAccount {
309
+ return this.accountSubscriber.getSpotMarketAccountAndSlot(
310
+ QUOTE_SPOT_MARKET_INDEX
311
+ ).data;
298
312
  }
299
313
 
300
314
  public getOraclePriceDataAndSlot(
@@ -303,6 +317,18 @@ export class ClearingHouse {
303
317
  return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
304
318
  }
305
319
 
320
+ public async getSerumV3FulfillmentConfig(
321
+ serumMarket: PublicKey
322
+ ): Promise<SerumV3FulfillmentConfigAccount> {
323
+ const address = await getSerumFulfillmentConfigPublicKey(
324
+ this.program.programId,
325
+ serumMarket
326
+ );
327
+ return (await this.program.account.serumV3FulfillmentConfig.fetch(
328
+ address
329
+ )) as SerumV3FulfillmentConfigAccount;
330
+ }
331
+
306
332
  /**
307
333
  * Update the wallet to use for clearing house transactions and linked user account
308
334
  * @param newWallet
@@ -433,6 +459,19 @@ export class ClearingHouse {
433
459
  });
434
460
  }
435
461
 
462
+ public async updateUserName(
463
+ name: string,
464
+ userId = 0
465
+ ): Promise<TransactionSignature> {
466
+ const nameBuffer = encodeName(name);
467
+ return await this.program.rpc.updateUserName(userId, nameBuffer, {
468
+ accounts: {
469
+ user: await this.getUserAccountPublicKey(),
470
+ authority: this.wallet.publicKey,
471
+ },
472
+ });
473
+ }
474
+
436
475
  public getUser(userId?: number): ClearingHouseUser {
437
476
  userId = userId ?? this.activeUserId;
438
477
  if (!this.users.has(userId)) {
@@ -476,29 +515,29 @@ export class ClearingHouse {
476
515
  return this.getUser(userId).getUserAccountAndSlot();
477
516
  }
478
517
 
479
- public getUserBankBalance(
480
- bankIndex: number | BN
481
- ): UserBankBalance | undefined {
482
- const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
483
- return this.getUserAccount().bankBalances.find((bankBalance) =>
484
- bankBalance.bankIndex.eq(bankIndexBN)
518
+ public getSpotPosition(marketIndex: number | BN): SpotPosition | undefined {
519
+ const marketIndexBN =
520
+ marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
521
+ return this.getUserAccount().spotPositions.find((spotPosition) =>
522
+ spotPosition.marketIndex.eq(marketIndexBN)
485
523
  );
486
524
  }
487
525
 
488
526
  public getQuoteAssetTokenAmount(): BN {
489
- const bank = this.getBankAccount(QUOTE_ASSET_BANK_INDEX);
490
- const userBankBalance = this.getUserBankBalance(QUOTE_ASSET_BANK_INDEX);
527
+ const spotMarket = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX);
528
+ const spotPosition = this.getSpotPosition(QUOTE_SPOT_MARKET_INDEX);
491
529
  return getTokenAmount(
492
- userBankBalance.balance,
493
- bank,
494
- userBankBalance.balanceType
530
+ spotPosition.balance,
531
+ spotMarket,
532
+ spotPosition.balanceType
495
533
  );
496
534
  }
497
535
 
498
536
  getRemainingAccounts(params: {
499
- writableMarketIndex?: BN;
500
- writableBankIndex?: BN;
501
- readableMarketIndex?: BN;
537
+ writablePerpMarketIndex?: BN;
538
+ writableSpotMarketIndex?: BN;
539
+ readablePerpMarketIndex?: BN;
540
+ readableSpotMarketIndex?: BN;
502
541
  }): AccountMeta[] {
503
542
  const userAccountAndSlot = this.getUserAccountAndSlot();
504
543
  if (!userAccountAndSlot) {
@@ -510,14 +549,14 @@ export class ClearingHouse {
510
549
  userAccountAndSlot;
511
550
 
512
551
  const oracleAccountMap = new Map<string, AccountMeta>();
513
- const bankAccountMap = new Map<number, AccountMeta>();
514
- const marketAccountMap = new Map<number, AccountMeta>();
552
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
553
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
515
554
  for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
516
555
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
517
556
  // otherwise remove from slot
518
557
  if (slot > lastUserPositionsSlot) {
519
- const marketAccount = this.getMarketAccount(marketIndexNum);
520
- marketAccountMap.set(marketIndexNum, {
558
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
559
+ perpMarketAccountMap.set(marketIndexNum, {
521
560
  pubkey: marketAccount.pubkey,
522
561
  isSigner: false,
523
562
  isWritable: false,
@@ -532,11 +571,11 @@ export class ClearingHouse {
532
571
  }
533
572
  }
534
573
 
535
- for (const position of userAccount.positions) {
574
+ for (const position of userAccount.perpPositions) {
536
575
  if (!positionIsAvailable(position)) {
537
576
  const marketIndexNum = position.marketIndex.toNumber();
538
- const marketAccount = this.getMarketAccount(marketIndexNum);
539
- marketAccountMap.set(marketIndexNum, {
577
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
578
+ perpMarketAccountMap.set(marketIndexNum, {
540
579
  pubkey: marketAccount.pubkey,
541
580
  isSigner: false,
542
581
  isWritable: false,
@@ -549,11 +588,11 @@ export class ClearingHouse {
549
588
  }
550
589
  }
551
590
 
552
- if (params.readableMarketIndex) {
553
- const marketAccount = this.getMarketAccount(
554
- params.readableMarketIndex.toNumber()
591
+ if (params.readablePerpMarketIndex) {
592
+ const marketAccount = this.getPerpMarketAccount(
593
+ params.readablePerpMarketIndex.toNumber()
555
594
  );
556
- marketAccountMap.set(params.readableMarketIndex.toNumber(), {
595
+ perpMarketAccountMap.set(params.readablePerpMarketIndex.toNumber(), {
557
596
  pubkey: marketAccount.pubkey,
558
597
  isSigner: false,
559
598
  isWritable: true,
@@ -565,11 +604,11 @@ export class ClearingHouse {
565
604
  });
566
605
  }
567
606
 
568
- if (params.writableMarketIndex) {
569
- const marketAccount = this.getMarketAccount(
570
- params.writableMarketIndex.toNumber()
607
+ if (params.writablePerpMarketIndex) {
608
+ const marketAccount = this.getPerpMarketAccount(
609
+ params.writablePerpMarketIndex.toNumber()
571
610
  );
572
- marketAccountMap.set(params.writableMarketIndex.toNumber(), {
611
+ perpMarketAccountMap.set(params.writablePerpMarketIndex.toNumber(), {
573
612
  pubkey: marketAccount.pubkey,
574
613
  isSigner: false,
575
614
  isWritable: true,
@@ -581,17 +620,19 @@ export class ClearingHouse {
581
620
  });
582
621
  }
583
622
 
584
- for (const userBankBalance of userAccount.bankBalances) {
585
- if (!userBankBalance.balance.eq(ZERO)) {
586
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
587
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
588
- pubkey: bankAccount.pubkey,
623
+ for (const spotPosition of userAccount.spotPositions) {
624
+ if (!isSpotPositionAvailable(spotPosition)) {
625
+ const spotMarketAccount = this.getSpotMarketAccount(
626
+ spotPosition.marketIndex
627
+ );
628
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
629
+ pubkey: spotMarketAccount.pubkey,
589
630
  isSigner: false,
590
631
  isWritable: false,
591
632
  });
592
- if (!bankAccount.bankIndex.eq(ZERO)) {
593
- oracleAccountMap.set(bankAccount.oracle.toString(), {
594
- pubkey: bankAccount.oracle,
633
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
634
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
635
+ pubkey: spotMarketAccount.oracle,
595
636
  isSigner: false,
596
637
  isWritable: false,
597
638
  });
@@ -599,16 +640,36 @@ export class ClearingHouse {
599
640
  }
600
641
  }
601
642
 
602
- if (params.writableBankIndex) {
603
- const bankAccount = this.getBankAccount(params.writableBankIndex);
604
- bankAccountMap.set(params.writableBankIndex.toNumber(), {
605
- pubkey: bankAccount.pubkey,
643
+ if (params.readableSpotMarketIndex) {
644
+ const spotMarketAccount = this.getSpotMarketAccount(
645
+ params.readableSpotMarketIndex
646
+ );
647
+ spotMarketAccountMap.set(params.readableSpotMarketIndex.toNumber(), {
648
+ pubkey: spotMarketAccount.pubkey,
649
+ isSigner: false,
650
+ isWritable: false,
651
+ });
652
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
653
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
654
+ pubkey: spotMarketAccount.oracle,
655
+ isSigner: false,
656
+ isWritable: false,
657
+ });
658
+ }
659
+ }
660
+
661
+ if (params.writableSpotMarketIndex) {
662
+ const spotMarketAccount = this.getSpotMarketAccount(
663
+ params.writableSpotMarketIndex
664
+ );
665
+ spotMarketAccountMap.set(params.writableSpotMarketIndex.toNumber(), {
666
+ pubkey: spotMarketAccount.pubkey,
606
667
  isSigner: false,
607
668
  isWritable: true,
608
669
  });
609
- if (!bankAccount.bankIndex.eq(ZERO)) {
610
- oracleAccountMap.set(bankAccount.oracle.toString(), {
611
- pubkey: bankAccount.oracle,
670
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
671
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
672
+ pubkey: spotMarketAccount.oracle,
612
673
  isSigner: false,
613
674
  isWritable: false,
614
675
  });
@@ -617,8 +678,8 @@ export class ClearingHouse {
617
678
 
618
679
  return [
619
680
  ...oracleAccountMap.values(),
620
- ...bankAccountMap.values(),
621
- ...marketAccountMap.values(),
681
+ ...spotMarketAccountMap.values(),
682
+ ...perpMarketAccountMap.values(),
622
683
  ];
623
684
  }
624
685
 
@@ -637,7 +698,7 @@ export class ClearingHouse {
637
698
 
638
699
  public async deposit(
639
700
  amount: BN,
640
- bankIndex: BN,
701
+ marketIndex: BN,
641
702
  collateralAccountPublicKey: PublicKey,
642
703
  userId?: number,
643
704
  reduceOnly = false
@@ -645,14 +706,14 @@ export class ClearingHouse {
645
706
  const tx = new Transaction();
646
707
  const additionalSigners: Array<Signer> = [];
647
708
 
648
- const bank = this.getBankAccount(bankIndex);
709
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
649
710
 
650
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
711
+ const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
651
712
 
652
713
  const authority = this.wallet.publicKey;
653
714
 
654
715
  const createWSOLTokenAccount =
655
- isSolBank && collateralAccountPublicKey.equals(authority);
716
+ isSolMarket && collateralAccountPublicKey.equals(authority);
656
717
 
657
718
  if (createWSOLTokenAccount) {
658
719
  const { ixs, signers, pubkey } =
@@ -669,7 +730,7 @@ export class ClearingHouse {
669
730
 
670
731
  const depositCollateralIx = await this.getDepositInstruction(
671
732
  amount,
672
- bankIndex,
733
+ marketIndex,
673
734
  collateralAccountPublicKey,
674
735
  userId,
675
736
  reduceOnly,
@@ -701,7 +762,7 @@ export class ClearingHouse {
701
762
 
702
763
  async getDepositInstruction(
703
764
  amount: BN,
704
- bankIndex: BN,
765
+ marketIndex: BN,
705
766
  userTokenAccount: PublicKey,
706
767
  userId?: number,
707
768
  reduceOnly = false,
@@ -718,35 +779,35 @@ export class ClearingHouse {
718
779
  let remainingAccounts = [];
719
780
  if (userInitialized) {
720
781
  remainingAccounts = this.getRemainingAccounts({
721
- writableBankIndex: bankIndex,
782
+ writableSpotMarketIndex: marketIndex,
722
783
  });
723
784
  } else {
724
- const bankAccount = this.getBankAccount(bankIndex);
725
- if (!bankAccount.oracle.equals(PublicKey.default)) {
785
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
786
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
726
787
  remainingAccounts.push({
727
- pubkey: bankAccount.oracle,
788
+ pubkey: spotMarketAccount.oracle,
728
789
  isSigner: false,
729
790
  isWritable: false,
730
791
  });
731
792
  }
732
793
  remainingAccounts.push({
733
- pubkey: bankAccount.pubkey,
794
+ pubkey: spotMarketAccount.pubkey,
734
795
  isSigner: false,
735
796
  isWritable: true,
736
797
  });
737
798
  }
738
799
 
739
- const bank = this.getBankAccount(bankIndex);
800
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
740
801
 
741
802
  return await this.program.instruction.deposit(
742
- bankIndex,
803
+ marketIndex,
743
804
  amount,
744
805
  reduceOnly,
745
806
  {
746
807
  accounts: {
747
808
  state: await this.getStatePublicKey(),
748
- bank: bank.pubkey,
749
- bankVault: bank.vault,
809
+ spotMarket: spotMarketAccount.pubkey,
810
+ spotMarketVault: spotMarketAccount.vault,
750
811
  user: userAccountPublicKey,
751
812
  userStats: this.getUserStatsAccountPublicKey(),
752
813
  userTokenAccount: userTokenAccount,
@@ -769,7 +830,7 @@ export class ClearingHouse {
769
830
  }
770
831
 
771
832
  private async getSolWithdrawalIxs(
772
- bankIndex: BN,
833
+ marketIndex: BN,
773
834
  amount: BN
774
835
  ): Promise<{
775
836
  ixs: anchor.web3.TransactionInstruction[];
@@ -801,7 +862,7 @@ export class ClearingHouse {
801
862
 
802
863
  const withdrawIx = await this.getWithdrawIx(
803
864
  amount,
804
- bankIndex,
865
+ marketIndex,
805
866
  pubkey,
806
867
  true
807
868
  );
@@ -868,7 +929,7 @@ export class ClearingHouse {
868
929
  * Creates the Clearing House User account for a user, and deposits some initial collateral
869
930
  * @param amount
870
931
  * @param userTokenAccount
871
- * @param bankIndex
932
+ * @param marketIndex
872
933
  * @param userId
873
934
  * @param name
874
935
  * @param fromUserId
@@ -877,7 +938,7 @@ export class ClearingHouse {
877
938
  public async initializeUserAccountAndDepositCollateral(
878
939
  amount: BN,
879
940
  userTokenAccount: PublicKey,
880
- bankIndex = new BN(0),
941
+ marketIndex = new BN(0),
881
942
  userId = 0,
882
943
  name = DEFAULT_USER_NAME,
883
944
  fromUserId?: number,
@@ -888,16 +949,16 @@ export class ClearingHouse {
888
949
 
889
950
  const additionalSigners: Array<Signer> = [];
890
951
 
891
- const bank = this.getBankAccount(bankIndex);
952
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
892
953
 
893
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
954
+ const isSolMarket = spotMarket.mint.equals(WRAPPED_SOL_MINT);
894
955
 
895
956
  const tx = new Transaction();
896
957
 
897
958
  const authority = this.wallet.publicKey;
898
959
 
899
960
  const createWSOLTokenAccount =
900
- isSolBank && userTokenAccount.equals(authority);
961
+ isSolMarket && userTokenAccount.equals(authority);
901
962
 
902
963
  if (createWSOLTokenAccount) {
903
964
  const {
@@ -917,10 +978,15 @@ export class ClearingHouse {
917
978
 
918
979
  const depositCollateralIx =
919
980
  fromUserId != null
920
- ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
981
+ ? await this.getTransferDepositIx(
982
+ amount,
983
+ marketIndex,
984
+ fromUserId,
985
+ userId
986
+ )
921
987
  : await this.getDepositInstruction(
922
988
  amount,
923
- bankIndex,
989
+ marketIndex,
924
990
  userTokenAccount,
925
991
  userId,
926
992
  false,
@@ -957,7 +1023,7 @@ export class ClearingHouse {
957
1023
  public async initializeUserAccountForDevnet(
958
1024
  userId = 0,
959
1025
  name = DEFAULT_USER_NAME,
960
- bankIndex: BN,
1026
+ marketIndex: BN,
961
1027
  tokenFaucet: TokenFaucet,
962
1028
  amount: BN,
963
1029
  referrerInfo?: ReferrerInfo
@@ -973,7 +1039,7 @@ export class ClearingHouse {
973
1039
 
974
1040
  const depositCollateralIx = await this.getDepositInstruction(
975
1041
  amount,
976
- bankIndex,
1042
+ marketIndex,
977
1043
  associateTokenPublicKey,
978
1044
  userId,
979
1045
  false,
@@ -994,21 +1060,21 @@ export class ClearingHouse {
994
1060
 
995
1061
  public async withdraw(
996
1062
  amount: BN,
997
- bankIndex: BN,
1063
+ marketIndex: BN,
998
1064
  userTokenAccount: PublicKey,
999
1065
  reduceOnly = false
1000
1066
  ): Promise<TransactionSignature> {
1001
1067
  const tx = new Transaction();
1002
1068
  const additionalSigners: Array<Signer> = [];
1003
1069
 
1004
- const bank = this.getBankAccount(bankIndex);
1070
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1005
1071
 
1006
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
1072
+ const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
1007
1073
 
1008
1074
  const authority = this.wallet.publicKey;
1009
1075
 
1010
1076
  const createWSOLTokenAccount =
1011
- isSolBank && userTokenAccount.equals(authority);
1077
+ isSolMarket && userTokenAccount.equals(authority);
1012
1078
 
1013
1079
  if (createWSOLTokenAccount) {
1014
1080
  const { ixs, signers, pubkey } =
@@ -1025,7 +1091,7 @@ export class ClearingHouse {
1025
1091
 
1026
1092
  const withdrawCollateral = await this.getWithdrawIx(
1027
1093
  amount,
1028
- bank.bankIndex,
1094
+ spotMarketAccount.marketIndex,
1029
1095
  userTokenAccount,
1030
1096
  reduceOnly
1031
1097
  );
@@ -1055,27 +1121,27 @@ export class ClearingHouse {
1055
1121
 
1056
1122
  public async getWithdrawIx(
1057
1123
  amount: BN,
1058
- bankIndex: BN,
1124
+ marketIndex: BN,
1059
1125
  userTokenAccount: PublicKey,
1060
1126
  reduceOnly = false
1061
1127
  ): Promise<TransactionInstruction> {
1062
1128
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1063
1129
 
1064
1130
  const remainingAccounts = this.getRemainingAccounts({
1065
- writableBankIndex: bankIndex,
1131
+ writableSpotMarketIndex: marketIndex,
1066
1132
  });
1067
1133
 
1068
- const bank = this.getBankAccount(bankIndex);
1134
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1069
1135
 
1070
1136
  return await this.program.instruction.withdraw(
1071
- bankIndex,
1137
+ marketIndex,
1072
1138
  amount,
1073
1139
  reduceOnly,
1074
1140
  {
1075
1141
  accounts: {
1076
1142
  state: await this.getStatePublicKey(),
1077
- bank: bank.pubkey,
1078
- bankVault: bank.vault,
1143
+ spotMarket: spotMarketAccount.pubkey,
1144
+ spotMarketVault: spotMarketAccount.vault,
1079
1145
  clearingHouseSigner: this.getSignerPublicKey(),
1080
1146
  user: userAccountPublicKey,
1081
1147
  userStats: this.getUserStatsAccountPublicKey(),
@@ -1090,13 +1156,18 @@ export class ClearingHouse {
1090
1156
 
1091
1157
  public async transferDeposit(
1092
1158
  amount: BN,
1093
- bankIndex: BN,
1159
+ marketIndex: BN,
1094
1160
  fromUserId: number,
1095
1161
  toUserId: number
1096
1162
  ): Promise<TransactionSignature> {
1097
1163
  const { txSig } = await this.txSender.send(
1098
1164
  wrapInTx(
1099
- await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
1165
+ await this.getTransferDepositIx(
1166
+ amount,
1167
+ marketIndex,
1168
+ fromUserId,
1169
+ toUserId
1170
+ )
1100
1171
  ),
1101
1172
  [],
1102
1173
  this.opts
@@ -1106,7 +1177,7 @@ export class ClearingHouse {
1106
1177
 
1107
1178
  public async getTransferDepositIx(
1108
1179
  amount: BN,
1109
- bankIndex: BN,
1180
+ marketIndex: BN,
1110
1181
  fromUserId: number,
1111
1182
  toUserId: number
1112
1183
  ): Promise<TransactionInstruction> {
@@ -1122,10 +1193,10 @@ export class ClearingHouse {
1122
1193
  );
1123
1194
 
1124
1195
  const remainingAccounts = this.getRemainingAccounts({
1125
- writableBankIndex: bankIndex,
1196
+ writableSpotMarketIndex: marketIndex,
1126
1197
  });
1127
1198
 
1128
- return await this.program.instruction.transferDeposit(bankIndex, amount, {
1199
+ return await this.program.instruction.transferDeposit(marketIndex, amount, {
1129
1200
  accounts: {
1130
1201
  authority: this.wallet.publicKey,
1131
1202
  fromUser,
@@ -1137,24 +1208,24 @@ export class ClearingHouse {
1137
1208
  });
1138
1209
  }
1139
1210
 
1140
- public async updateBankCumulativeInterest(
1141
- bankIndex: BN
1211
+ public async updateSpotMarketCumulativeInterest(
1212
+ marketIndex: BN
1142
1213
  ): Promise<TransactionSignature> {
1143
1214
  const { txSig } = await this.txSender.send(
1144
- wrapInTx(await this.updateBankCumulativeInterestIx(bankIndex)),
1215
+ wrapInTx(await this.updateSpotMarketCumulativeInterestIx(marketIndex)),
1145
1216
  [],
1146
1217
  this.opts
1147
1218
  );
1148
1219
  return txSig;
1149
1220
  }
1150
1221
 
1151
- public async updateBankCumulativeInterestIx(
1152
- bankIndex: BN
1222
+ public async updateSpotMarketCumulativeInterestIx(
1223
+ marketIndex: BN
1153
1224
  ): Promise<TransactionInstruction> {
1154
- const bank = this.getBankAccount(bankIndex);
1155
- return await this.program.instruction.updateBankCumulativeInterest({
1225
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
1226
+ return await this.program.instruction.updateSpotMarketCumulativeInterest({
1156
1227
  accounts: {
1157
- bank: bank.pubkey,
1228
+ spotMarket: spotMarket.pubkey,
1158
1229
  },
1159
1230
  });
1160
1231
  }
@@ -1178,7 +1249,7 @@ export class ClearingHouse {
1178
1249
  const settleeUserAccount = (await this.program.account.user.fetch(
1179
1250
  settleeUserAccountPublicKey
1180
1251
  )) as UserAccount;
1181
- const userPositions = settleeUserAccount.positions;
1252
+ const userPositions = settleeUserAccount.perpPositions;
1182
1253
  const remainingAccounts = [];
1183
1254
 
1184
1255
  let foundMarket = false;
@@ -1234,15 +1305,15 @@ export class ClearingHouse {
1234
1305
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1235
1306
 
1236
1307
  const remainingAccounts = this.getRemainingAccounts({
1237
- writableMarketIndex: marketIndex,
1308
+ writablePerpMarketIndex: marketIndex,
1238
1309
  });
1239
1310
 
1240
1311
  if (sharesToBurn == undefined) {
1241
1312
  const userAccount = this.getUserAccount();
1242
- const marketPosition = userAccount.positions.filter((position) =>
1313
+ const perpPosition = userAccount.perpPositions.filter((position) =>
1243
1314
  position.marketIndex.eq(marketIndex)
1244
1315
  )[0];
1245
- sharesToBurn = marketPosition.lpShares;
1316
+ sharesToBurn = perpPosition.lpShares;
1246
1317
  console.log('burning lp shares:', sharesToBurn.toString());
1247
1318
  }
1248
1319
 
@@ -1275,7 +1346,7 @@ export class ClearingHouse {
1275
1346
  ): Promise<TransactionInstruction> {
1276
1347
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1277
1348
  const remainingAccounts = this.getRemainingAccounts({
1278
- writableMarketIndex: marketIndex,
1349
+ writablePerpMarketIndex: marketIndex,
1279
1350
  });
1280
1351
 
1281
1352
  return this.program.instruction.addLiquidity(amount, marketIndex, {
@@ -1303,6 +1374,60 @@ export class ClearingHouse {
1303
1374
  });
1304
1375
  }
1305
1376
 
1377
+ public async sendSignedTx(tx: Transaction): Promise<TransactionSignature> {
1378
+ const { txSig } = await this.txSender.send(tx, undefined, this.opts, true);
1379
+
1380
+ return txSig;
1381
+ }
1382
+
1383
+ /**
1384
+ * Sends a market order and returns a signed tx which can fill the order against the vamm, which the caller can use to fill their own order if required.
1385
+ * @param orderParams
1386
+ * @param userAccountPublicKey
1387
+ * @param userAccount
1388
+ * @returns
1389
+ */
1390
+ public async sendMarketOrderAndGetSignedFillTx(
1391
+ orderParams: OptionalOrderParams,
1392
+ userAccountPublicKey: PublicKey,
1393
+ userAccount: UserAccount
1394
+ ): Promise<{ txSig: TransactionSignature; signedFillTx: Transaction }> {
1395
+ const marketIndex = orderParams.marketIndex;
1396
+ const orderId = userAccount.nextOrderId;
1397
+
1398
+ const marketOrderTx = wrapInTx(await this.getPlaceOrderIx(orderParams));
1399
+ const fillTx = wrapInTx(
1400
+ await this.getFillOrderIx(userAccountPublicKey, userAccount, {
1401
+ orderId,
1402
+ marketIndex,
1403
+ })
1404
+ );
1405
+
1406
+ // Apply the latest blockhash to the txs so that we can sign before sending them
1407
+ const currentBlockHash = (
1408
+ await this.connection.getLatestBlockhash('finalized')
1409
+ ).blockhash;
1410
+ marketOrderTx.recentBlockhash = currentBlockHash;
1411
+ fillTx.recentBlockhash = currentBlockHash;
1412
+
1413
+ marketOrderTx.feePayer = userAccount.authority;
1414
+ fillTx.feePayer = userAccount.authority;
1415
+
1416
+ const [signedMarketOrderTx, signedFillTx] =
1417
+ await this.provider.wallet.signAllTransactions([marketOrderTx, fillTx]);
1418
+
1419
+ const { txSig, slot } = await this.txSender.send(
1420
+ signedMarketOrderTx,
1421
+ [],
1422
+ this.opts,
1423
+ true
1424
+ );
1425
+
1426
+ this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1427
+
1428
+ return { txSig, signedFillTx };
1429
+ }
1430
+
1306
1431
  public async placeOrder(
1307
1432
  orderParams: OptionalOrderParams
1308
1433
  ): Promise<TransactionSignature> {
@@ -1315,18 +1440,23 @@ export class ClearingHouse {
1315
1440
  return txSig;
1316
1441
  }
1317
1442
 
1318
- getOrderParams(optionalOrderParams: OptionalOrderParams): OrderParams {
1319
- return Object.assign({}, DefaultOrderParams, optionalOrderParams);
1443
+ getOrderParams(
1444
+ optionalOrderParams: OptionalOrderParams,
1445
+ marketType: MarketType
1446
+ ): OrderParams {
1447
+ return Object.assign({}, DefaultOrderParams, optionalOrderParams, {
1448
+ marketType,
1449
+ });
1320
1450
  }
1321
1451
 
1322
1452
  public async getPlaceOrderIx(
1323
1453
  orderParams: OptionalOrderParams
1324
1454
  ): Promise<TransactionInstruction> {
1325
- orderParams = this.getOrderParams(orderParams);
1455
+ orderParams = this.getOrderParams(orderParams, MarketType.PERP);
1326
1456
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1327
1457
 
1328
1458
  const remainingAccounts = this.getRemainingAccounts({
1329
- readableMarketIndex: orderParams.marketIndex,
1459
+ readablePerpMarketIndex: orderParams.marketIndex,
1330
1460
  });
1331
1461
 
1332
1462
  return await this.program.instruction.placeOrder(orderParams, {
@@ -1359,7 +1489,7 @@ export class ClearingHouse {
1359
1489
  const oracleAccountInfos = [];
1360
1490
  for (const marketIndex of marketIndexes) {
1361
1491
  if (!marketIndex.eq(new BN(100))) {
1362
- const market = this.getMarketAccount(marketIndex);
1492
+ const market = this.getPerpMarketAccount(marketIndex);
1363
1493
  marketAccountInfos.push({
1364
1494
  pubkey: market.pubkey,
1365
1495
  isWritable: true,
@@ -1383,6 +1513,54 @@ export class ClearingHouse {
1383
1513
  });
1384
1514
  }
1385
1515
 
1516
+ public async settleExpiredMarket(
1517
+ marketIndex: BN
1518
+ ): Promise<TransactionSignature> {
1519
+ const { txSig } = await this.txSender.send(
1520
+ wrapInTx(await this.getSettleExpiredMarketIx(marketIndex)),
1521
+ [],
1522
+ this.opts
1523
+ );
1524
+ return txSig;
1525
+ }
1526
+
1527
+ public async getSettleExpiredMarketIx(
1528
+ marketIndex: BN
1529
+ ): Promise<TransactionInstruction> {
1530
+ const marketAccountInfos = [];
1531
+ const oracleAccountInfos = [];
1532
+ const spotMarketAccountInfos = [];
1533
+ const market = this.getPerpMarketAccount(marketIndex);
1534
+ marketAccountInfos.push({
1535
+ pubkey: market.pubkey,
1536
+ isWritable: true,
1537
+ isSigner: false,
1538
+ });
1539
+ oracleAccountInfos.push({
1540
+ pubkey: market.amm.oracle,
1541
+ isWritable: false,
1542
+ isSigner: false,
1543
+ });
1544
+
1545
+ spotMarketAccountInfos.push({
1546
+ pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
1547
+ isSigner: false,
1548
+ isWritable: true,
1549
+ });
1550
+
1551
+ const remainingAccounts = oracleAccountInfos
1552
+ .concat(spotMarketAccountInfos)
1553
+ .concat(marketAccountInfos);
1554
+
1555
+ return await this.program.instruction.settleExpiredMarket(marketIndex, {
1556
+ accounts: {
1557
+ state: await this.getStatePublicKey(),
1558
+ authority: this.wallet.publicKey,
1559
+ },
1560
+ remainingAccounts,
1561
+ });
1562
+ }
1563
+
1386
1564
  public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
1387
1565
  const { txSig } = await this.txSender.send(
1388
1566
  wrapInTx(await this.getCancelOrderIx(orderId)),
@@ -1424,7 +1602,7 @@ export class ClearingHouse {
1424
1602
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1425
1603
 
1426
1604
  const order = this.getOrderByUserId(userOrderId);
1427
- const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
1605
+ const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
1428
1606
 
1429
1607
  const remainingAccounts = this.getRemainingAccounts({});
1430
1608
 
@@ -1465,7 +1643,7 @@ export class ClearingHouse {
1465
1643
  public async getFillOrderIx(
1466
1644
  userAccountPublicKey: PublicKey,
1467
1645
  userAccount: UserAccount,
1468
- order: Order,
1646
+ order: Pick<Order, 'marketIndex' | 'orderId'>,
1469
1647
  makerInfo?: MakerInfo,
1470
1648
  referrerInfo?: ReferrerInfo
1471
1649
  ): Promise<TransactionInstruction> {
@@ -1482,24 +1660,26 @@ export class ClearingHouse {
1482
1660
  : userAccount.orders.find((order) =>
1483
1661
  order.orderId.eq(userAccount.nextOrderId.sub(ONE))
1484
1662
  ).marketIndex;
1485
- const marketAccount = this.getMarketAccount(marketIndex);
1663
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
1486
1664
 
1487
1665
  const oracleAccountMap = new Map<string, AccountMeta>();
1488
- const bankAccountMap = new Map<number, AccountMeta>();
1489
- const marketAccountMap = new Map<number, AccountMeta>();
1666
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
1667
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
1490
1668
 
1491
- for (const bankBalance of userAccount.bankBalances) {
1492
- if (!bankBalance.balance.eq(ZERO)) {
1493
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1494
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1495
- pubkey: bankAccount.pubkey,
1669
+ for (const spotPosition of userAccount.spotPositions) {
1670
+ if (!isSpotPositionAvailable(spotPosition)) {
1671
+ const spotMarketAccount = this.getSpotMarketAccount(
1672
+ spotPosition.marketIndex
1673
+ );
1674
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
1675
+ pubkey: spotMarketAccount.pubkey,
1496
1676
  isSigner: false,
1497
1677
  isWritable: false,
1498
1678
  });
1499
1679
 
1500
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1501
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1502
- pubkey: bankAccount.oracle,
1680
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
1681
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1682
+ pubkey: spotMarketAccount.oracle,
1503
1683
  isSigner: false,
1504
1684
  isWritable: false,
1505
1685
  });
@@ -1507,13 +1687,13 @@ export class ClearingHouse {
1507
1687
  }
1508
1688
  }
1509
1689
 
1510
- for (const position of userAccount.positions) {
1690
+ for (const position of userAccount.perpPositions) {
1511
1691
  if (
1512
1692
  !positionIsAvailable(position) &&
1513
1693
  !position.marketIndex.eq(order.marketIndex)
1514
1694
  ) {
1515
- const market = this.getMarketAccount(position.marketIndex);
1516
- marketAccountMap.set(position.marketIndex.toNumber(), {
1695
+ const market = this.getPerpMarketAccount(position.marketIndex);
1696
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
1517
1697
  pubkey: market.pubkey,
1518
1698
  isWritable: false,
1519
1699
  isSigner: false,
@@ -1526,7 +1706,7 @@ export class ClearingHouse {
1526
1706
  }
1527
1707
  }
1528
1708
 
1529
- marketAccountMap.set(marketIndex.toNumber(), {
1709
+ perpMarketAccountMap.set(marketIndex.toNumber(), {
1530
1710
  pubkey: marketAccount.pubkey,
1531
1711
  isWritable: true,
1532
1712
  isSigner: false,
@@ -1539,8 +1719,8 @@ export class ClearingHouse {
1539
1719
 
1540
1720
  const remainingAccounts = [
1541
1721
  ...oracleAccountMap.values(),
1542
- ...bankAccountMap.values(),
1543
- ...marketAccountMap.values(),
1722
+ ...spotMarketAccountMap.values(),
1723
+ ...perpMarketAccountMap.values(),
1544
1724
  ];
1545
1725
 
1546
1726
  if (makerInfo) {
@@ -1585,45 +1765,101 @@ export class ClearingHouse {
1585
1765
  });
1586
1766
  }
1587
1767
 
1588
- public async triggerOrder(
1768
+ public async placeSpotOrder(
1769
+ orderParams: OptionalOrderParams
1770
+ ): Promise<TransactionSignature> {
1771
+ const { txSig } = await this.txSender.send(
1772
+ wrapInTx(await this.getPlaceSpotOrderIx(orderParams)),
1773
+ [],
1774
+ this.opts
1775
+ );
1776
+ return txSig;
1777
+ }
1778
+
1779
+ public async getPlaceSpotOrderIx(
1780
+ orderParams: OptionalOrderParams
1781
+ ): Promise<TransactionInstruction> {
1782
+ orderParams = this.getOrderParams(orderParams, MarketType.SPOT);
1783
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
1784
+
1785
+ const remainingAccounts = this.getRemainingAccounts({
1786
+ readableSpotMarketIndex: orderParams.marketIndex,
1787
+ });
1788
+
1789
+ return await this.program.instruction.placeSpotOrder(orderParams, {
1790
+ accounts: {
1791
+ state: await this.getStatePublicKey(),
1792
+ user: userAccountPublicKey,
1793
+ userStats: this.getUserStatsAccountPublicKey(),
1794
+ authority: this.wallet.publicKey,
1795
+ },
1796
+ remainingAccounts,
1797
+ });
1798
+ }
1799
+
1800
+ public async fillSpotOrder(
1589
1801
  userAccountPublicKey: PublicKey,
1590
1802
  user: UserAccount,
1591
- order: Order
1803
+ order?: Order,
1804
+ fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
1805
+ makerInfo?: MakerInfo,
1806
+ referrerInfo?: ReferrerInfo
1592
1807
  ): Promise<TransactionSignature> {
1593
1808
  const { txSig } = await this.txSender.send(
1594
- wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
1809
+ wrapInTx(
1810
+ await this.getFillSpotOrderIx(
1811
+ userAccountPublicKey,
1812
+ user,
1813
+ order,
1814
+ fulfillmentConfig,
1815
+ makerInfo,
1816
+ referrerInfo
1817
+ )
1818
+ ),
1595
1819
  [],
1596
1820
  this.opts
1597
1821
  );
1598
1822
  return txSig;
1599
1823
  }
1600
1824
 
1601
- public async getTriggerOrderIx(
1825
+ public async getFillSpotOrderIx(
1602
1826
  userAccountPublicKey: PublicKey,
1603
1827
  userAccount: UserAccount,
1604
- order: Order
1828
+ order?: Order,
1829
+ fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
1830
+ makerInfo?: MakerInfo,
1831
+ referrerInfo?: ReferrerInfo
1605
1832
  ): Promise<TransactionInstruction> {
1833
+ const userStatsPublicKey = getUserStatsAccountPublicKey(
1834
+ this.program.programId,
1835
+ userAccount.authority
1836
+ );
1837
+
1606
1838
  const fillerPublicKey = await this.getUserAccountPublicKey();
1839
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1607
1840
 
1608
- const marketIndex = order.marketIndex;
1609
- const marketAccount = this.getMarketAccount(marketIndex);
1841
+ const marketIndex = order
1842
+ ? order.marketIndex
1843
+ : userAccount.orders.find((order) =>
1844
+ order.orderId.eq(userAccount.nextOrderId.sub(ONE))
1845
+ ).marketIndex;
1610
1846
 
1611
1847
  const oracleAccountMap = new Map<string, AccountMeta>();
1612
- const bankAccountMap = new Map<number, AccountMeta>();
1613
- const marketAccountMap = new Map<number, AccountMeta>();
1614
-
1615
- for (const bankBalance of userAccount.bankBalances) {
1616
- if (!bankBalance.balance.eq(ZERO)) {
1617
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1618
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1619
- pubkey: bankAccount.pubkey,
1848
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
1849
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
1850
+
1851
+ for (const spotPosition of userAccount.spotPositions) {
1852
+ if (!isSpotPositionAvailable(spotPosition)) {
1853
+ const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
1854
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
1855
+ pubkey: spotMarket.pubkey,
1620
1856
  isSigner: false,
1621
1857
  isWritable: false,
1622
1858
  });
1623
1859
 
1624
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1625
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1626
- pubkey: bankAccount.oracle,
1860
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
1861
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
1862
+ pubkey: spotMarket.oracle,
1627
1863
  isSigner: false,
1628
1864
  isWritable: false,
1629
1865
  });
@@ -1631,13 +1867,13 @@ export class ClearingHouse {
1631
1867
  }
1632
1868
  }
1633
1869
 
1634
- for (const position of userAccount.positions) {
1870
+ for (const position of userAccount.perpPositions) {
1635
1871
  if (
1636
1872
  !positionIsAvailable(position) &&
1637
1873
  !position.marketIndex.eq(order.marketIndex)
1638
1874
  ) {
1639
- const market = this.getMarketAccount(position.marketIndex);
1640
- marketAccountMap.set(position.marketIndex.toNumber(), {
1875
+ const market = this.getPerpMarketAccount(position.marketIndex);
1876
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
1641
1877
  pubkey: market.pubkey,
1642
1878
  isWritable: false,
1643
1879
  isSigner: false,
@@ -1650,77 +1886,42 @@ export class ClearingHouse {
1650
1886
  }
1651
1887
  }
1652
1888
 
1653
- marketAccountMap.set(marketIndex.toNumber(), {
1654
- pubkey: marketAccount.pubkey,
1889
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1890
+ spotMarketAccountMap.set(marketIndex.toNumber(), {
1891
+ pubkey: spotMarketAccount.pubkey,
1655
1892
  isWritable: true,
1656
1893
  isSigner: false,
1657
1894
  });
1658
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1659
- pubkey: marketAccount.amm.oracle,
1660
- isWritable: false,
1895
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
1896
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1897
+ pubkey: spotMarketAccount.oracle,
1898
+ isWritable: false,
1899
+ isSigner: false,
1900
+ });
1901
+ }
1902
+ const quoteMarketAccount = this.getQuoteSpotMarketAccount();
1903
+ spotMarketAccountMap.set(quoteMarketAccount.marketIndex.toNumber(), {
1904
+ pubkey: quoteMarketAccount.pubkey,
1905
+ isWritable: true,
1661
1906
  isSigner: false,
1662
1907
  });
1663
1908
 
1664
1909
  const remainingAccounts = [
1665
1910
  ...oracleAccountMap.values(),
1666
- ...bankAccountMap.values(),
1667
- ...marketAccountMap.values(),
1911
+ ...spotMarketAccountMap.values(),
1912
+ ...perpMarketAccountMap.values(),
1668
1913
  ];
1669
1914
 
1670
- const orderId = order.orderId;
1671
- return await this.program.instruction.triggerOrder(orderId, {
1672
- accounts: {
1673
- state: await this.getStatePublicKey(),
1674
- filler: fillerPublicKey,
1675
- user: userAccountPublicKey,
1676
- authority: this.wallet.publicKey,
1677
- },
1678
- remainingAccounts,
1679
- });
1680
- }
1681
-
1682
- public async placeAndTake(
1683
- orderParams: OptionalOrderParams,
1684
- makerInfo?: MakerInfo,
1685
- referrerInfo?: ReferrerInfo
1686
- ): Promise<TransactionSignature> {
1687
- const { txSig, slot } = await this.txSender.send(
1688
- wrapInTx(
1689
- await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
1690
- ),
1691
- [],
1692
- this.opts
1693
- );
1694
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1695
- return txSig;
1696
- }
1697
-
1698
- public async getPlaceAndTakeIx(
1699
- orderParams: OptionalOrderParams,
1700
- makerInfo?: MakerInfo,
1701
- referrerInfo?: ReferrerInfo
1702
- ): Promise<TransactionInstruction> {
1703
- orderParams = this.getOrderParams(orderParams);
1704
- const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
1705
- const userAccountPublicKey = await this.getUserAccountPublicKey();
1706
-
1707
- const remainingAccounts = this.getRemainingAccounts({
1708
- writableMarketIndex: orderParams.marketIndex,
1709
- writableBankIndex: QUOTE_ASSET_BANK_INDEX,
1710
- });
1711
-
1712
- let makerOrderId = null;
1713
1915
  if (makerInfo) {
1714
- makerOrderId = makerInfo.order.orderId;
1715
1916
  remainingAccounts.push({
1716
1917
  pubkey: makerInfo.maker,
1717
- isSigner: false,
1718
1918
  isWritable: true,
1919
+ isSigner: false,
1719
1920
  });
1720
1921
  remainingAccounts.push({
1721
1922
  pubkey: makerInfo.makerStats,
1722
- isSigner: false,
1723
1923
  isWritable: true,
1924
+ isSigner: false,
1724
1925
  });
1725
1926
  }
1726
1927
 
@@ -1737,24 +1938,385 @@ export class ClearingHouse {
1737
1938
  });
1738
1939
  }
1739
1940
 
1740
- return await this.program.instruction.placeAndTake(
1741
- orderParams,
1742
- makerOrderId,
1743
- {
1744
- accounts: {
1745
- state: await this.getStatePublicKey(),
1746
- user: userAccountPublicKey,
1747
- userStats: userStatsPublicKey,
1748
- authority: this.wallet.publicKey,
1749
- },
1750
- remainingAccounts,
1751
- }
1752
- );
1753
- }
1941
+ const orderId = order.orderId;
1942
+ const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1754
1943
 
1755
- public async placeAndMake(
1756
- orderParams: OptionalOrderParams,
1757
- takerInfo: TakerInfo,
1944
+ if (fulfillmentConfig) {
1945
+ remainingAccounts.push({
1946
+ pubkey: fulfillmentConfig.pubkey,
1947
+ isWritable: false,
1948
+ isSigner: false,
1949
+ });
1950
+ remainingAccounts.push({
1951
+ pubkey: fulfillmentConfig.serumProgramId,
1952
+ isWritable: false,
1953
+ isSigner: false,
1954
+ });
1955
+ remainingAccounts.push({
1956
+ pubkey: fulfillmentConfig.serumMarket,
1957
+ isWritable: true,
1958
+ isSigner: false,
1959
+ });
1960
+ remainingAccounts.push({
1961
+ pubkey: fulfillmentConfig.serumRequestQueue,
1962
+ isWritable: true,
1963
+ isSigner: false,
1964
+ });
1965
+ remainingAccounts.push({
1966
+ pubkey: fulfillmentConfig.serumEventQueue,
1967
+ isWritable: true,
1968
+ isSigner: false,
1969
+ });
1970
+ remainingAccounts.push({
1971
+ pubkey: fulfillmentConfig.serumBids,
1972
+ isWritable: true,
1973
+ isSigner: false,
1974
+ });
1975
+ remainingAccounts.push({
1976
+ pubkey: fulfillmentConfig.serumAsks,
1977
+ isWritable: true,
1978
+ isSigner: false,
1979
+ });
1980
+ remainingAccounts.push({
1981
+ pubkey: fulfillmentConfig.serumBaseVault,
1982
+ isWritable: true,
1983
+ isSigner: false,
1984
+ });
1985
+ remainingAccounts.push({
1986
+ pubkey: fulfillmentConfig.serumQuoteVault,
1987
+ isWritable: true,
1988
+ isSigner: false,
1989
+ });
1990
+ remainingAccounts.push({
1991
+ pubkey: fulfillmentConfig.serumOpenOrders,
1992
+ isWritable: true,
1993
+ isSigner: false,
1994
+ });
1995
+ remainingAccounts.push({
1996
+ pubkey: getSerumSignerPublicKey(
1997
+ fulfillmentConfig.serumProgramId,
1998
+ fulfillmentConfig.serumMarket,
1999
+ fulfillmentConfig.serumSignerNonce
2000
+ ),
2001
+ isWritable: false,
2002
+ isSigner: false,
2003
+ });
2004
+ remainingAccounts.push({
2005
+ pubkey: this.getSignerPublicKey(),
2006
+ isWritable: false,
2007
+ isSigner: false,
2008
+ });
2009
+ remainingAccounts.push({
2010
+ pubkey: TOKEN_PROGRAM_ID,
2011
+ isWritable: false,
2012
+ isSigner: false,
2013
+ });
2014
+ remainingAccounts.push({
2015
+ pubkey: spotMarketAccount.vault,
2016
+ isWritable: true,
2017
+ isSigner: false,
2018
+ });
2019
+ remainingAccounts.push({
2020
+ pubkey: quoteMarketAccount.vault,
2021
+ isWritable: true,
2022
+ isSigner: false,
2023
+ });
2024
+ }
2025
+
2026
+ return await this.program.instruction.fillSpotOrder(
2027
+ orderId,
2028
+ fulfillmentConfig ? fulfillmentConfig.fulfillmentType : null,
2029
+ makerOrderId,
2030
+ {
2031
+ accounts: {
2032
+ state: await this.getStatePublicKey(),
2033
+ filler: fillerPublicKey,
2034
+ fillerStats: fillerStatsPublicKey,
2035
+ user: userAccountPublicKey,
2036
+ userStats: userStatsPublicKey,
2037
+ authority: this.wallet.publicKey,
2038
+ },
2039
+ remainingAccounts,
2040
+ }
2041
+ );
2042
+ }
2043
+
2044
+ public async triggerOrder(
2045
+ userAccountPublicKey: PublicKey,
2046
+ user: UserAccount,
2047
+ order: Order
2048
+ ): Promise<TransactionSignature> {
2049
+ const { txSig } = await this.txSender.send(
2050
+ wrapInTx(await this.getTriggerOrderIx(userAccountPublicKey, user, order)),
2051
+ [],
2052
+ this.opts
2053
+ );
2054
+ return txSig;
2055
+ }
2056
+
2057
+ public async getTriggerOrderIx(
2058
+ userAccountPublicKey: PublicKey,
2059
+ userAccount: UserAccount,
2060
+ order: Order
2061
+ ): Promise<TransactionInstruction> {
2062
+ const fillerPublicKey = await this.getUserAccountPublicKey();
2063
+
2064
+ const marketIndex = order.marketIndex;
2065
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
2066
+
2067
+ const oracleAccountMap = new Map<string, AccountMeta>();
2068
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2069
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
2070
+
2071
+ for (const spotPosition of userAccount.spotPositions) {
2072
+ if (!isSpotPositionAvailable(spotPosition)) {
2073
+ const spotMarketAccount = this.getSpotMarketAccount(
2074
+ spotPosition.marketIndex
2075
+ );
2076
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
2077
+ pubkey: spotMarketAccount.pubkey,
2078
+ isSigner: false,
2079
+ isWritable: false,
2080
+ });
2081
+
2082
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
2083
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
2084
+ pubkey: spotMarketAccount.oracle,
2085
+ isSigner: false,
2086
+ isWritable: false,
2087
+ });
2088
+ }
2089
+ }
2090
+ }
2091
+
2092
+ for (const position of userAccount.perpPositions) {
2093
+ if (
2094
+ !positionIsAvailable(position) &&
2095
+ !position.marketIndex.eq(order.marketIndex)
2096
+ ) {
2097
+ const market = this.getPerpMarketAccount(position.marketIndex);
2098
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
2099
+ pubkey: market.pubkey,
2100
+ isWritable: false,
2101
+ isSigner: false,
2102
+ });
2103
+ oracleAccountMap.set(market.amm.oracle.toString(), {
2104
+ pubkey: market.amm.oracle,
2105
+ isWritable: false,
2106
+ isSigner: false,
2107
+ });
2108
+ }
2109
+ }
2110
+
2111
+ perpMarketAccountMap.set(marketIndex.toNumber(), {
2112
+ pubkey: marketAccount.pubkey,
2113
+ isWritable: true,
2114
+ isSigner: false,
2115
+ });
2116
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
2117
+ pubkey: marketAccount.amm.oracle,
2118
+ isWritable: false,
2119
+ isSigner: false,
2120
+ });
2121
+
2122
+ const remainingAccounts = [
2123
+ ...oracleAccountMap.values(),
2124
+ ...spotMarketAccountMap.values(),
2125
+ ...perpMarketAccountMap.values(),
2126
+ ];
2127
+
2128
+ const orderId = order.orderId;
2129
+ return await this.program.instruction.triggerOrder(orderId, {
2130
+ accounts: {
2131
+ state: await this.getStatePublicKey(),
2132
+ filler: fillerPublicKey,
2133
+ user: userAccountPublicKey,
2134
+ authority: this.wallet.publicKey,
2135
+ },
2136
+ remainingAccounts,
2137
+ });
2138
+ }
2139
+
2140
+ public async triggerSpotOrder(
2141
+ userAccountPublicKey: PublicKey,
2142
+ user: UserAccount,
2143
+ order: Order
2144
+ ): Promise<TransactionSignature> {
2145
+ const { txSig } = await this.txSender.send(
2146
+ wrapInTx(
2147
+ await this.getTriggerSpotOrderIx(userAccountPublicKey, user, order)
2148
+ ),
2149
+ [],
2150
+ this.opts
2151
+ );
2152
+ return txSig;
2153
+ }
2154
+
2155
+ public async getTriggerSpotOrderIx(
2156
+ userAccountPublicKey: PublicKey,
2157
+ userAccount: UserAccount,
2158
+ order: Order
2159
+ ): Promise<TransactionInstruction> {
2160
+ const fillerPublicKey = await this.getUserAccountPublicKey();
2161
+
2162
+ const marketIndex = order.marketIndex;
2163
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2164
+
2165
+ const oracleAccountMap = new Map<string, AccountMeta>();
2166
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2167
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
2168
+
2169
+ for (const spotPosition of userAccount.spotPositions) {
2170
+ if (!isSpotPositionAvailable(spotPosition)) {
2171
+ const spotMarketAccount = this.getSpotMarketAccount(
2172
+ spotPosition.marketIndex
2173
+ );
2174
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
2175
+ pubkey: spotMarketAccount.pubkey,
2176
+ isSigner: false,
2177
+ isWritable: false,
2178
+ });
2179
+
2180
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
2181
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
2182
+ pubkey: spotMarketAccount.oracle,
2183
+ isSigner: false,
2184
+ isWritable: false,
2185
+ });
2186
+ }
2187
+ }
2188
+ }
2189
+
2190
+ for (const position of userAccount.perpPositions) {
2191
+ if (
2192
+ !positionIsAvailable(position) &&
2193
+ !position.marketIndex.eq(order.marketIndex)
2194
+ ) {
2195
+ const market = this.getPerpMarketAccount(position.marketIndex);
2196
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
2197
+ pubkey: market.pubkey,
2198
+ isWritable: false,
2199
+ isSigner: false,
2200
+ });
2201
+ oracleAccountMap.set(market.amm.oracle.toString(), {
2202
+ pubkey: market.amm.oracle,
2203
+ isWritable: false,
2204
+ isSigner: false,
2205
+ });
2206
+ }
2207
+ }
2208
+
2209
+ const quoteSpotMarket = this.getQuoteSpotMarketAccount();
2210
+ spotMarketAccountMap.set(quoteSpotMarket.marketIndex.toNumber(), {
2211
+ pubkey: quoteSpotMarket.pubkey,
2212
+ isWritable: true,
2213
+ isSigner: false,
2214
+ });
2215
+ spotMarketAccountMap.set(marketIndex.toNumber(), {
2216
+ pubkey: spotMarketAccount.pubkey,
2217
+ isWritable: false,
2218
+ isSigner: false,
2219
+ });
2220
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
2221
+ pubkey: spotMarketAccount.oracle,
2222
+ isWritable: false,
2223
+ isSigner: false,
2224
+ });
2225
+
2226
+ const remainingAccounts = [
2227
+ ...oracleAccountMap.values(),
2228
+ ...spotMarketAccountMap.values(),
2229
+ ...perpMarketAccountMap.values(),
2230
+ ];
2231
+
2232
+ const orderId = order.orderId;
2233
+ return await this.program.instruction.triggerSpotOrder(orderId, {
2234
+ accounts: {
2235
+ state: await this.getStatePublicKey(),
2236
+ filler: fillerPublicKey,
2237
+ user: userAccountPublicKey,
2238
+ authority: this.wallet.publicKey,
2239
+ },
2240
+ remainingAccounts,
2241
+ });
2242
+ }
2243
+
2244
+ public async placeAndTake(
2245
+ orderParams: OptionalOrderParams,
2246
+ makerInfo?: MakerInfo,
2247
+ referrerInfo?: ReferrerInfo
2248
+ ): Promise<TransactionSignature> {
2249
+ const { txSig, slot } = await this.txSender.send(
2250
+ wrapInTx(
2251
+ await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
2252
+ ),
2253
+ [],
2254
+ this.opts
2255
+ );
2256
+ this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
2257
+ return txSig;
2258
+ }
2259
+
2260
+ public async getPlaceAndTakeIx(
2261
+ orderParams: OptionalOrderParams,
2262
+ makerInfo?: MakerInfo,
2263
+ referrerInfo?: ReferrerInfo
2264
+ ): Promise<TransactionInstruction> {
2265
+ orderParams = this.getOrderParams(orderParams, MarketType.PERP);
2266
+ const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
2267
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
2268
+
2269
+ const remainingAccounts = this.getRemainingAccounts({
2270
+ writablePerpMarketIndex: orderParams.marketIndex,
2271
+ writableSpotMarketIndex: QUOTE_SPOT_MARKET_INDEX,
2272
+ });
2273
+
2274
+ let makerOrderId = null;
2275
+ if (makerInfo) {
2276
+ makerOrderId = makerInfo.order.orderId;
2277
+ remainingAccounts.push({
2278
+ pubkey: makerInfo.maker,
2279
+ isSigner: false,
2280
+ isWritable: true,
2281
+ });
2282
+ remainingAccounts.push({
2283
+ pubkey: makerInfo.makerStats,
2284
+ isSigner: false,
2285
+ isWritable: true,
2286
+ });
2287
+ }
2288
+
2289
+ if (referrerInfo) {
2290
+ remainingAccounts.push({
2291
+ pubkey: referrerInfo.referrer,
2292
+ isWritable: true,
2293
+ isSigner: false,
2294
+ });
2295
+ remainingAccounts.push({
2296
+ pubkey: referrerInfo.referrerStats,
2297
+ isWritable: true,
2298
+ isSigner: false,
2299
+ });
2300
+ }
2301
+
2302
+ return await this.program.instruction.placeAndTake(
2303
+ orderParams,
2304
+ makerOrderId,
2305
+ {
2306
+ accounts: {
2307
+ state: await this.getStatePublicKey(),
2308
+ user: userAccountPublicKey,
2309
+ userStats: userStatsPublicKey,
2310
+ authority: this.wallet.publicKey,
2311
+ },
2312
+ remainingAccounts,
2313
+ }
2314
+ );
2315
+ }
2316
+
2317
+ public async placeAndMake(
2318
+ orderParams: OptionalOrderParams,
2319
+ takerInfo: TakerInfo,
1758
2320
  referrerInfo?: ReferrerInfo
1759
2321
  ): Promise<TransactionSignature> {
1760
2322
  const { txSig, slot } = await this.txSender.send(
@@ -1775,14 +2337,14 @@ export class ClearingHouse {
1775
2337
  takerInfo: TakerInfo,
1776
2338
  referrerInfo?: ReferrerInfo
1777
2339
  ): Promise<TransactionInstruction> {
1778
- orderParams = this.getOrderParams(orderParams);
2340
+ orderParams = this.getOrderParams(orderParams, MarketType.PERP);
1779
2341
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1780
2342
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1781
2343
 
1782
2344
  // todo merge this with getRemainingAccounts
1783
2345
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1784
2346
  counterPartyUserAccount: takerInfo.takerUserAccount,
1785
- writableMarketIndex: orderParams.marketIndex,
2347
+ writablePerpMarketIndex: orderParams.marketIndex,
1786
2348
  });
1787
2349
 
1788
2350
  if (referrerInfo) {
@@ -1895,13 +2457,110 @@ export class ClearingHouse {
1895
2457
  settleeUserAccount: UserAccount,
1896
2458
  marketIndex: BN
1897
2459
  ): Promise<TransactionInstruction> {
1898
- const marketAccountMap = new Map<number, AccountMeta>();
2460
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
1899
2461
  const oracleAccountMap = new Map<string, AccountMeta>();
1900
- const bankAccountMap = new Map<number, AccountMeta>();
2462
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2463
+
2464
+ for (const position of settleeUserAccount.perpPositions) {
2465
+ if (!positionIsAvailable(position)) {
2466
+ const market = this.getPerpMarketAccount(position.marketIndex);
2467
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
2468
+ pubkey: market.pubkey,
2469
+ isWritable: false,
2470
+ isSigner: false,
2471
+ });
2472
+ oracleAccountMap.set(market.amm.oracle.toString(), {
2473
+ pubkey: market.amm.oracle,
2474
+ isWritable: false,
2475
+ isSigner: false,
2476
+ });
2477
+ }
2478
+ }
2479
+
2480
+ for (const spotPosition of settleeUserAccount.spotPositions) {
2481
+ if (!isSpotPositionAvailable(spotPosition)) {
2482
+ const spotMarketAccount = this.getSpotMarketAccount(
2483
+ spotPosition.marketIndex
2484
+ );
2485
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
2486
+ pubkey: spotMarketAccount.pubkey,
2487
+ isSigner: false,
2488
+ isWritable: false,
2489
+ });
2490
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
2491
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
2492
+ pubkey: spotMarketAccount.oracle,
2493
+ isSigner: false,
2494
+ isWritable: false,
2495
+ });
2496
+ }
2497
+ }
2498
+ }
1901
2499
 
1902
- for (const position of settleeUserAccount.positions) {
2500
+ const marketAccount = this.getPerpMarketAccount(marketIndex.toNumber());
2501
+ perpMarketAccountMap.set(marketIndex.toNumber(), {
2502
+ pubkey: marketAccount.pubkey,
2503
+ isSigner: false,
2504
+ isWritable: true,
2505
+ });
2506
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
2507
+ pubkey: marketAccount.amm.oracle,
2508
+ isSigner: false,
2509
+ isWritable: false,
2510
+ });
2511
+
2512
+ spotMarketAccountMap.set(QUOTE_SPOT_MARKET_INDEX.toNumber(), {
2513
+ pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
2514
+ isSigner: false,
2515
+ isWritable: true,
2516
+ });
2517
+
2518
+ const remainingAccounts = [
2519
+ ...oracleAccountMap.values(),
2520
+ ...spotMarketAccountMap.values(),
2521
+ ...perpMarketAccountMap.values(),
2522
+ ];
2523
+
2524
+ return await this.program.instruction.settlePnl(marketIndex, {
2525
+ accounts: {
2526
+ state: await this.getStatePublicKey(),
2527
+ authority: this.wallet.publicKey,
2528
+ user: settleeUserAccountPublicKey,
2529
+ },
2530
+ remainingAccounts: remainingAccounts,
2531
+ });
2532
+ }
2533
+
2534
+ public async settleExpiredPosition(
2535
+ settleeUserAccountPublicKey: PublicKey,
2536
+ settleeUserAccount: UserAccount,
2537
+ marketIndex: BN
2538
+ ): Promise<TransactionSignature> {
2539
+ const { txSig } = await this.txSender.send(
2540
+ wrapInTx(
2541
+ await this.getSettleExpiredPositionIx(
2542
+ settleeUserAccountPublicKey,
2543
+ settleeUserAccount,
2544
+ marketIndex
2545
+ )
2546
+ ),
2547
+ [],
2548
+ this.opts
2549
+ );
2550
+ return txSig;
2551
+ }
2552
+
2553
+ public async getSettleExpiredPositionIx(
2554
+ settleeUserAccountPublicKey: PublicKey,
2555
+ settleeUserAccount: UserAccount,
2556
+ marketIndex: BN
2557
+ ): Promise<TransactionInstruction> {
2558
+ const marketAccountMap = new Map<number, AccountMeta>();
2559
+ const oracleAccountMap = new Map<string, AccountMeta>();
2560
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2561
+ for (const position of settleeUserAccount.perpPositions) {
1903
2562
  if (!positionIsAvailable(position)) {
1904
- const market = this.getMarketAccount(position.marketIndex);
2563
+ const market = this.getPerpMarketAccount(position.marketIndex);
1905
2564
  marketAccountMap.set(position.marketIndex.toNumber(), {
1906
2565
  pubkey: market.pubkey,
1907
2566
  isWritable: false,
@@ -1915,15 +2574,17 @@ export class ClearingHouse {
1915
2574
  }
1916
2575
  }
1917
2576
 
1918
- for (const userBankBalance of settleeUserAccount.bankBalances) {
1919
- if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
1920
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
1921
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
2577
+ for (const userBankBalance of settleeUserAccount.spotPositions) {
2578
+ if (!userBankBalance.balance.eq(ZERO)) {
2579
+ const bankAccount = this.getSpotMarketAccount(
2580
+ userBankBalance.marketIndex
2581
+ );
2582
+ spotMarketAccountMap.set(userBankBalance.marketIndex.toNumber(), {
1922
2583
  pubkey: bankAccount.pubkey,
1923
2584
  isSigner: false,
1924
2585
  isWritable: false,
1925
2586
  });
1926
- if (!bankAccount.bankIndex.eq(ZERO)) {
2587
+ if (!bankAccount.marketIndex.eq(ZERO)) {
1927
2588
  oracleAccountMap.set(bankAccount.oracle.toString(), {
1928
2589
  pubkey: bankAccount.oracle,
1929
2590
  isSigner: false,
@@ -1933,7 +2594,7 @@ export class ClearingHouse {
1933
2594
  }
1934
2595
  }
1935
2596
 
1936
- const marketAccount = this.getMarketAccount(marketIndex.toNumber());
2597
+ const marketAccount = this.getPerpMarketAccount(marketIndex.toNumber());
1937
2598
  marketAccountMap.set(marketIndex.toNumber(), {
1938
2599
  pubkey: marketAccount.pubkey,
1939
2600
  isSigner: false,
@@ -1945,19 +2606,19 @@ export class ClearingHouse {
1945
2606
  isWritable: false,
1946
2607
  });
1947
2608
 
1948
- bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
1949
- pubkey: this.getBankAccount(QUOTE_ASSET_BANK_INDEX).pubkey,
2609
+ spotMarketAccountMap.set(QUOTE_SPOT_MARKET_INDEX.toNumber(), {
2610
+ pubkey: this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX).pubkey,
1950
2611
  isSigner: false,
1951
2612
  isWritable: true,
1952
2613
  });
1953
2614
 
1954
2615
  const remainingAccounts = [
1955
2616
  ...oracleAccountMap.values(),
1956
- ...bankAccountMap.values(),
2617
+ ...spotMarketAccountMap.values(),
1957
2618
  ...marketAccountMap.values(),
1958
2619
  ];
1959
2620
 
1960
- return await this.program.instruction.settlePnl(marketIndex, {
2621
+ return await this.program.instruction.settleExpiredPosition(marketIndex, {
1961
2622
  accounts: {
1962
2623
  state: await this.getStatePublicKey(),
1963
2624
  authority: this.wallet.publicKey,
@@ -1973,7 +2634,7 @@ export class ClearingHouse {
1973
2634
  marketIndex: BN,
1974
2635
  maxBaseAssetAmount: BN
1975
2636
  ): Promise<TransactionSignature> {
1976
- const { txSig } = await this.txSender.send(
2637
+ const { txSig, slot } = await this.txSender.send(
1977
2638
  wrapInTx(
1978
2639
  await this.getLiquidatePerpIx(
1979
2640
  userAccountPublicKey,
@@ -1985,6 +2646,7 @@ export class ClearingHouse {
1985
2646
  [],
1986
2647
  this.opts
1987
2648
  );
2649
+ this.marketLastSlotCache.set(marketIndex.toNumber(), slot);
1988
2650
  return txSig;
1989
2651
  }
1990
2652
 
@@ -2003,7 +2665,7 @@ export class ClearingHouse {
2003
2665
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
2004
2666
 
2005
2667
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2006
- writableMarketIndex: marketIndex,
2668
+ writablePerpMarketIndex: marketIndex,
2007
2669
  counterPartyUserAccount: userAccount,
2008
2670
  });
2009
2671
 
@@ -2027,8 +2689,8 @@ export class ClearingHouse {
2027
2689
  public async liquidateBorrow(
2028
2690
  userAccountPublicKey: PublicKey,
2029
2691
  userAccount: UserAccount,
2030
- assetBankIndex: BN,
2031
- liabilityBankIndex: BN,
2692
+ assetmarketIndex: BN,
2693
+ liabilitymarketIndex: BN,
2032
2694
  maxLiabilityTransfer: BN
2033
2695
  ): Promise<TransactionSignature> {
2034
2696
  const { txSig } = await this.txSender.send(
@@ -2036,8 +2698,8 @@ export class ClearingHouse {
2036
2698
  await this.getLiquidateBorrowIx(
2037
2699
  userAccountPublicKey,
2038
2700
  userAccount,
2039
- assetBankIndex,
2040
- liabilityBankIndex,
2701
+ assetmarketIndex,
2702
+ liabilitymarketIndex,
2041
2703
  maxLiabilityTransfer
2042
2704
  )
2043
2705
  ),
@@ -2050,20 +2712,20 @@ export class ClearingHouse {
2050
2712
  public async getLiquidateBorrowIx(
2051
2713
  userAccountPublicKey: PublicKey,
2052
2714
  userAccount: UserAccount,
2053
- assetBankIndex: BN,
2054
- liabilityBankIndex: BN,
2715
+ assetmarketIndex: BN,
2716
+ liabilitymarketIndex: BN,
2055
2717
  maxLiabilityTransfer: BN
2056
2718
  ): Promise<TransactionInstruction> {
2057
2719
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2058
2720
 
2059
2721
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2060
2722
  counterPartyUserAccount: userAccount,
2061
- writableBankIndexes: [liabilityBankIndex, assetBankIndex],
2723
+ writableSpotMarketIndexes: [liabilitymarketIndex, assetmarketIndex],
2062
2724
  });
2063
2725
 
2064
2726
  return await this.program.instruction.liquidateBorrow(
2065
- assetBankIndex,
2066
- liabilityBankIndex,
2727
+ assetmarketIndex,
2728
+ liabilitymarketIndex,
2067
2729
  maxLiabilityTransfer,
2068
2730
  {
2069
2731
  accounts: {
@@ -2081,22 +2743,23 @@ export class ClearingHouse {
2081
2743
  userAccountPublicKey: PublicKey,
2082
2744
  userAccount: UserAccount,
2083
2745
  perpMarketIndex: BN,
2084
- liabilityBankIndex: BN,
2746
+ liabilitymarketIndex: BN,
2085
2747
  maxLiabilityTransfer: BN
2086
2748
  ): Promise<TransactionSignature> {
2087
- const { txSig } = await this.txSender.send(
2749
+ const { txSig, slot } = await this.txSender.send(
2088
2750
  wrapInTx(
2089
2751
  await this.getLiquidateBorrowForPerpPnlIx(
2090
2752
  userAccountPublicKey,
2091
2753
  userAccount,
2092
2754
  perpMarketIndex,
2093
- liabilityBankIndex,
2755
+ liabilitymarketIndex,
2094
2756
  maxLiabilityTransfer
2095
2757
  )
2096
2758
  ),
2097
2759
  [],
2098
2760
  this.opts
2099
2761
  );
2762
+ this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
2100
2763
  return txSig;
2101
2764
  }
2102
2765
 
@@ -2104,20 +2767,20 @@ export class ClearingHouse {
2104
2767
  userAccountPublicKey: PublicKey,
2105
2768
  userAccount: UserAccount,
2106
2769
  perpMarketIndex: BN,
2107
- liabilityBankIndex: BN,
2770
+ liabilitymarketIndex: BN,
2108
2771
  maxLiabilityTransfer: BN
2109
2772
  ): Promise<TransactionInstruction> {
2110
2773
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2111
2774
 
2112
2775
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2113
2776
  counterPartyUserAccount: userAccount,
2114
- writableMarketIndex: perpMarketIndex,
2115
- writableBankIndexes: [liabilityBankIndex],
2777
+ writablePerpMarketIndex: perpMarketIndex,
2778
+ writableSpotMarketIndexes: [liabilitymarketIndex],
2116
2779
  });
2117
2780
 
2118
2781
  return await this.program.instruction.liquidateBorrowForPerpPnl(
2119
2782
  perpMarketIndex,
2120
- liabilityBankIndex,
2783
+ liabilitymarketIndex,
2121
2784
  maxLiabilityTransfer,
2122
2785
  {
2123
2786
  accounts: {
@@ -2135,22 +2798,23 @@ export class ClearingHouse {
2135
2798
  userAccountPublicKey: PublicKey,
2136
2799
  userAccount: UserAccount,
2137
2800
  perpMarketIndex: BN,
2138
- assetBankIndex: BN,
2801
+ assetMarketIndex: BN,
2139
2802
  maxPnlTransfer: BN
2140
2803
  ): Promise<TransactionSignature> {
2141
- const { txSig } = await this.txSender.send(
2804
+ const { txSig, slot } = await this.txSender.send(
2142
2805
  wrapInTx(
2143
2806
  await this.getLiquidatePerpPnlForDepositIx(
2144
2807
  userAccountPublicKey,
2145
2808
  userAccount,
2146
2809
  perpMarketIndex,
2147
- assetBankIndex,
2810
+ assetMarketIndex,
2148
2811
  maxPnlTransfer
2149
2812
  )
2150
2813
  ),
2151
2814
  [],
2152
2815
  this.opts
2153
2816
  );
2817
+ this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
2154
2818
  return txSig;
2155
2819
  }
2156
2820
 
@@ -2158,20 +2822,20 @@ export class ClearingHouse {
2158
2822
  userAccountPublicKey: PublicKey,
2159
2823
  userAccount: UserAccount,
2160
2824
  perpMarketIndex: BN,
2161
- assetBankIndex: BN,
2825
+ assetMarketIndex: BN,
2162
2826
  maxPnlTransfer: BN
2163
2827
  ): Promise<TransactionInstruction> {
2164
2828
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2165
2829
 
2166
2830
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2167
2831
  counterPartyUserAccount: userAccount,
2168
- writableMarketIndex: perpMarketIndex,
2169
- writableBankIndexes: [assetBankIndex],
2832
+ writablePerpMarketIndex: perpMarketIndex,
2833
+ writableSpotMarketIndexes: [assetMarketIndex],
2170
2834
  });
2171
2835
 
2172
2836
  return await this.program.instruction.liquidatePerpPnlForDeposit(
2173
2837
  perpMarketIndex,
2174
- assetBankIndex,
2838
+ assetMarketIndex,
2175
2839
  maxPnlTransfer,
2176
2840
  {
2177
2841
  accounts: {
@@ -2188,7 +2852,6 @@ export class ClearingHouse {
2188
2852
  public async resolvePerpBankruptcy(
2189
2853
  userAccountPublicKey: PublicKey,
2190
2854
  userAccount: UserAccount,
2191
- bankIndex: BN,
2192
2855
  marketIndex: BN
2193
2856
  ): Promise<TransactionSignature> {
2194
2857
  const { txSig } = await this.txSender.send(
@@ -2196,7 +2859,6 @@ export class ClearingHouse {
2196
2859
  await this.getResolvePerpBankruptcyIx(
2197
2860
  userAccountPublicKey,
2198
2861
  userAccount,
2199
- bankIndex,
2200
2862
  marketIndex
2201
2863
  )
2202
2864
  ),
@@ -2209,21 +2871,20 @@ export class ClearingHouse {
2209
2871
  public async getResolvePerpBankruptcyIx(
2210
2872
  userAccountPublicKey: PublicKey,
2211
2873
  userAccount: UserAccount,
2212
- bankIndex: BN,
2213
2874
  marketIndex: BN
2214
2875
  ): Promise<TransactionInstruction> {
2215
2876
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2216
2877
 
2217
2878
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2218
- writableMarketIndex: marketIndex,
2219
- writableBankIndexes: [bankIndex],
2879
+ writablePerpMarketIndex: marketIndex,
2880
+ writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
2220
2881
  counterPartyUserAccount: userAccount,
2221
2882
  });
2222
2883
 
2223
- const bank = this.getBankAccount(bankIndex);
2884
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2224
2885
 
2225
2886
  return await this.program.instruction.resolvePerpBankruptcy(
2226
- bankIndex,
2887
+ QUOTE_SPOT_MARKET_INDEX,
2227
2888
  marketIndex,
2228
2889
  {
2229
2890
  accounts: {
@@ -2231,8 +2892,8 @@ export class ClearingHouse {
2231
2892
  authority: this.wallet.publicKey,
2232
2893
  user: userAccountPublicKey,
2233
2894
  liquidator: liquidatorPublicKey,
2234
- bankVault: bank.vault,
2235
- insuranceFundVault: bank.insuranceFundVault,
2895
+ spotMarketVault: spotMarket.vault,
2896
+ insuranceFundVault: spotMarket.insuranceFundVault,
2236
2897
  clearingHouseSigner: this.getSignerPublicKey(),
2237
2898
  tokenProgram: TOKEN_PROGRAM_ID,
2238
2899
  },
@@ -2244,14 +2905,14 @@ export class ClearingHouse {
2244
2905
  public async resolveBorrowBankruptcy(
2245
2906
  userAccountPublicKey: PublicKey,
2246
2907
  userAccount: UserAccount,
2247
- bankIndex: BN
2908
+ marketIndex: BN
2248
2909
  ): Promise<TransactionSignature> {
2249
2910
  const { txSig } = await this.txSender.send(
2250
2911
  wrapInTx(
2251
2912
  await this.getResolveBorrowBankruptcyIx(
2252
2913
  userAccountPublicKey,
2253
2914
  userAccount,
2254
- bankIndex
2915
+ marketIndex
2255
2916
  )
2256
2917
  ),
2257
2918
  [],
@@ -2263,25 +2924,25 @@ export class ClearingHouse {
2263
2924
  public async getResolveBorrowBankruptcyIx(
2264
2925
  userAccountPublicKey: PublicKey,
2265
2926
  userAccount: UserAccount,
2266
- bankIndex: BN
2927
+ marketIndex: BN
2267
2928
  ): Promise<TransactionInstruction> {
2268
2929
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2269
2930
 
2270
2931
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2271
- writableBankIndexes: [bankIndex],
2932
+ writableSpotMarketIndexes: [marketIndex],
2272
2933
  counterPartyUserAccount: userAccount,
2273
2934
  });
2274
2935
 
2275
- const bank = this.getBankAccount(bankIndex);
2936
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2276
2937
 
2277
- return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
2938
+ return await this.program.instruction.resolveBorrowBankruptcy(marketIndex, {
2278
2939
  accounts: {
2279
2940
  state: await this.getStatePublicKey(),
2280
2941
  authority: this.wallet.publicKey,
2281
2942
  user: userAccountPublicKey,
2282
2943
  liquidator: liquidatorPublicKey,
2283
- bankVault: bank.vault,
2284
- insuranceFundVault: bank.insuranceFundVault,
2944
+ spotMarketVault: spotMarket.vault,
2945
+ insuranceFundVault: spotMarket.insuranceFundVault,
2285
2946
  clearingHouseSigner: this.getSignerPublicKey(),
2286
2947
  tokenProgram: TOKEN_PROGRAM_ID,
2287
2948
  },
@@ -2291,35 +2952,35 @@ export class ClearingHouse {
2291
2952
 
2292
2953
  getRemainingAccountsWithCounterparty(params: {
2293
2954
  counterPartyUserAccount: UserAccount;
2294
- writableMarketIndex?: BN;
2295
- writableBankIndexes?: BN[];
2955
+ writablePerpMarketIndex?: BN;
2956
+ writableSpotMarketIndexes?: BN[];
2296
2957
  }): AccountMeta[] {
2297
2958
  const counterPartyUserAccount = params.counterPartyUserAccount;
2298
2959
 
2299
2960
  const oracleAccountMap = new Map<string, AccountMeta>();
2300
- const bankAccountMap = new Map<number, AccountMeta>();
2961
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2301
2962
  const marketAccountMap = new Map<number, AccountMeta>();
2302
- for (const bankBalance of counterPartyUserAccount.bankBalances) {
2303
- if (!bankBalance.balance.eq(ZERO)) {
2304
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
2305
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
2306
- pubkey: bankAccount.pubkey,
2963
+ for (const spotPosition of counterPartyUserAccount.spotPositions) {
2964
+ if (!isSpotPositionAvailable(spotPosition)) {
2965
+ const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
2966
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
2967
+ pubkey: spotMarket.pubkey,
2307
2968
  isSigner: false,
2308
2969
  isWritable: false,
2309
2970
  });
2310
2971
 
2311
- if (!bankAccount.oracle.equals(PublicKey.default)) {
2312
- oracleAccountMap.set(bankAccount.oracle.toString(), {
2313
- pubkey: bankAccount.oracle,
2972
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
2973
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
2974
+ pubkey: spotMarket.oracle,
2314
2975
  isSigner: false,
2315
2976
  isWritable: false,
2316
2977
  });
2317
2978
  }
2318
2979
  }
2319
2980
  }
2320
- for (const position of counterPartyUserAccount.positions) {
2981
+ for (const position of counterPartyUserAccount.perpPositions) {
2321
2982
  if (!positionIsAvailable(position)) {
2322
- const market = this.getMarketAccount(position.marketIndex);
2983
+ const market = this.getPerpMarketAccount(position.marketIndex);
2323
2984
  marketAccountMap.set(position.marketIndex.toNumber(), {
2324
2985
  pubkey: market.pubkey,
2325
2986
  isWritable: false,
@@ -2346,7 +3007,7 @@ export class ClearingHouse {
2346
3007
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
2347
3008
  // otherwise remove from slot
2348
3009
  if (slot > lastUserPositionsSlot) {
2349
- const marketAccount = this.getMarketAccount(marketIndexNum);
3010
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
2350
3011
  marketAccountMap.set(marketIndexNum, {
2351
3012
  pubkey: marketAccount.pubkey,
2352
3013
  isSigner: false,
@@ -2361,27 +3022,27 @@ export class ClearingHouse {
2361
3022
  this.marketLastSlotCache.delete(marketIndexNum);
2362
3023
  }
2363
3024
  }
2364
- for (const bankBalance of userAccount.bankBalances) {
2365
- if (!bankBalance.balance.eq(ZERO)) {
2366
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
2367
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
2368
- pubkey: bankAccount.pubkey,
3025
+ for (const spotPosition of userAccount.spotPositions) {
3026
+ if (!isSpotPositionAvailable(spotPosition)) {
3027
+ const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
3028
+ spotMarketAccountMap.set(spotPosition.marketIndex.toNumber(), {
3029
+ pubkey: spotMarket.pubkey,
2369
3030
  isSigner: false,
2370
3031
  isWritable: false,
2371
3032
  });
2372
3033
 
2373
- if (!bankAccount.oracle.equals(PublicKey.default)) {
2374
- oracleAccountMap.set(bankAccount.oracle.toString(), {
2375
- pubkey: bankAccount.oracle,
3034
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
3035
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
3036
+ pubkey: spotMarket.oracle,
2376
3037
  isSigner: false,
2377
3038
  isWritable: false,
2378
3039
  });
2379
3040
  }
2380
3041
  }
2381
3042
  }
2382
- for (const position of userAccount.positions) {
3043
+ for (const position of userAccount.perpPositions) {
2383
3044
  if (!positionIsAvailable(position)) {
2384
- const market = this.getMarketAccount(position.marketIndex);
3045
+ const market = this.getPerpMarketAccount(position.marketIndex);
2385
3046
  marketAccountMap.set(position.marketIndex.toNumber(), {
2386
3047
  pubkey: market.pubkey,
2387
3048
  isWritable: false,
@@ -2395,8 +3056,8 @@ export class ClearingHouse {
2395
3056
  }
2396
3057
  }
2397
3058
 
2398
- if (params.writableMarketIndex) {
2399
- const market = this.getMarketAccount(params.writableMarketIndex);
3059
+ if (params.writablePerpMarketIndex) {
3060
+ const market = this.getPerpMarketAccount(params.writablePerpMarketIndex);
2400
3061
  marketAccountMap.set(market.marketIndex.toNumber(), {
2401
3062
  pubkey: market.pubkey,
2402
3063
  isSigner: false,
@@ -2409,17 +3070,19 @@ export class ClearingHouse {
2409
3070
  });
2410
3071
  }
2411
3072
 
2412
- if (params.writableBankIndexes) {
2413
- for (const writableBankIndex of params.writableBankIndexes) {
2414
- const bank = this.getBankAccount(writableBankIndex);
2415
- bankAccountMap.set(bank.bankIndex.toNumber(), {
2416
- pubkey: bank.pubkey,
3073
+ if (params.writableSpotMarketIndexes) {
3074
+ for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
3075
+ const spotMarketAccount = this.getSpotMarketAccount(
3076
+ writableSpotMarketIndex
3077
+ );
3078
+ spotMarketAccountMap.set(spotMarketAccount.marketIndex.toNumber(), {
3079
+ pubkey: spotMarketAccount.pubkey,
2417
3080
  isSigner: false,
2418
3081
  isWritable: true,
2419
3082
  });
2420
- if (!bank.oracle.equals(PublicKey.default)) {
2421
- oracleAccountMap.set(bank.oracle.toString(), {
2422
- pubkey: bank.oracle,
3083
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
3084
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
3085
+ pubkey: spotMarketAccount.oracle,
2423
3086
  isSigner: false,
2424
3087
  isWritable: false,
2425
3088
  });
@@ -2429,7 +3092,7 @@ export class ClearingHouse {
2429
3092
 
2430
3093
  return [
2431
3094
  ...oracleAccountMap.values(),
2432
- ...bankAccountMap.values(),
3095
+ ...spotMarketAccountMap.values(),
2433
3096
  ...marketAccountMap.values(),
2434
3097
  ];
2435
3098
  }
@@ -2477,7 +3140,7 @@ export class ClearingHouse {
2477
3140
  userAccount
2478
3141
  )) as UserAccount;
2479
3142
 
2480
- const userPositions = user.positions;
3143
+ const userPositions = user.perpPositions;
2481
3144
 
2482
3145
  const remainingAccounts = [];
2483
3146
  for (const position of userPositions) {
@@ -2508,17 +3171,17 @@ export class ClearingHouse {
2508
3171
  }
2509
3172
 
2510
3173
  public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
2511
- const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
3174
+ const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
2512
3175
  const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
2513
3176
 
2514
3177
  return oracleData;
2515
3178
  }
2516
3179
 
2517
3180
  public async initializeInsuranceFundStake(
2518
- bankIndex: BN
3181
+ marketIndex: BN
2519
3182
  ): Promise<TransactionSignature> {
2520
3183
  const { txSig } = await this.txSender.send(
2521
- wrapInTx(await this.getInitializeInsuranceFundStakeIx(bankIndex)),
3184
+ wrapInTx(await this.getInitializeInsuranceFundStakeIx(marketIndex)),
2522
3185
  [],
2523
3186
  this.opts
2524
3187
  );
@@ -2526,20 +3189,20 @@ export class ClearingHouse {
2526
3189
  }
2527
3190
 
2528
3191
  public async getInitializeInsuranceFundStakeIx(
2529
- bankIndex: BN
3192
+ marketIndex: BN
2530
3193
  ): Promise<TransactionInstruction> {
2531
3194
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2532
3195
  this.program.programId,
2533
3196
  this.wallet.publicKey,
2534
- bankIndex
3197
+ marketIndex
2535
3198
  );
2536
3199
 
2537
3200
  return await this.program.instruction.initializeInsuranceFundStake(
2538
- bankIndex,
3201
+ marketIndex,
2539
3202
  {
2540
3203
  accounts: {
2541
3204
  insuranceFundStake: ifStakeAccountPublicKey,
2542
- bank: this.getBankAccount(bankIndex).pubkey,
3205
+ spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
2543
3206
  userStats: this.getUserStatsAccountPublicKey(),
2544
3207
  authority: this.wallet.publicKey,
2545
3208
  payer: this.wallet.publicKey,
@@ -2552,29 +3215,29 @@ export class ClearingHouse {
2552
3215
  }
2553
3216
 
2554
3217
  public async addInsuranceFundStake(
2555
- bankIndex: BN,
3218
+ marketIndex: BN,
2556
3219
  amount: BN,
2557
3220
  collateralAccountPublicKey: PublicKey
2558
3221
  ): Promise<TransactionSignature> {
2559
- const bank = this.getBankAccount(bankIndex);
3222
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2560
3223
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2561
3224
  this.program.programId,
2562
3225
  this.wallet.publicKey,
2563
- bankIndex
3226
+ marketIndex
2564
3227
  );
2565
3228
 
2566
3229
  const remainingAccounts = this.getRemainingAccounts({
2567
- writableBankIndex: bankIndex,
3230
+ writableSpotMarketIndex: marketIndex,
2568
3231
  });
2569
3232
 
2570
- return await this.program.rpc.addInsuranceFundStake(bankIndex, amount, {
3233
+ return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
2571
3234
  accounts: {
2572
3235
  state: await this.getStatePublicKey(),
2573
- bank: bank.pubkey,
3236
+ spotMarket: spotMarket.pubkey,
2574
3237
  insuranceFundStake: ifStakeAccountPublicKey,
2575
3238
  userStats: this.getUserStatsAccountPublicKey(),
2576
3239
  authority: this.wallet.publicKey,
2577
- insuranceFundVault: bank.insuranceFundVault,
3240
+ insuranceFundVault: spotMarket.insuranceFundVault,
2578
3241
  userTokenAccount: collateralAccountPublicKey,
2579
3242
  tokenProgram: TOKEN_PROGRAM_ID,
2580
3243
  },
@@ -2583,31 +3246,31 @@ export class ClearingHouse {
2583
3246
  }
2584
3247
 
2585
3248
  public async requestRemoveInsuranceFundStake(
2586
- bankIndex: BN,
3249
+ marketIndex: BN,
2587
3250
  amount: BN
2588
3251
  ): Promise<TransactionSignature> {
2589
- const bank = this.getBankAccount(bankIndex);
3252
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2590
3253
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2591
3254
  this.program.programId,
2592
3255
  this.wallet.publicKey,
2593
- bankIndex
3256
+ marketIndex
2594
3257
  );
2595
3258
 
2596
3259
  const remainingAccounts = this.getRemainingAccounts({
2597
- writableBankIndex: bankIndex,
3260
+ writableSpotMarketIndex: marketIndex,
2598
3261
  });
2599
3262
 
2600
3263
  return await this.program.rpc.requestRemoveInsuranceFundStake(
2601
- bankIndex,
3264
+ marketIndex,
2602
3265
  amount,
2603
3266
  {
2604
3267
  accounts: {
2605
3268
  state: await this.getStatePublicKey(),
2606
- bank: bank.pubkey,
3269
+ spotMarket: spotMarketAccount.pubkey,
2607
3270
  insuranceFundStake: ifStakeAccountPublicKey,
2608
3271
  userStats: this.getUserStatsAccountPublicKey(),
2609
3272
  authority: this.wallet.publicKey,
2610
- insuranceFundVault: bank.insuranceFundVault,
3273
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2611
3274
  // userTokenAccount: collateralAccountPublicKey,
2612
3275
  // tokenProgram: TOKEN_PROGRAM_ID,
2613
3276
  },
@@ -2617,29 +3280,29 @@ export class ClearingHouse {
2617
3280
  }
2618
3281
 
2619
3282
  public async cancelRequestRemoveInsuranceFundStake(
2620
- bankIndex: BN
3283
+ marketIndex: BN
2621
3284
  ): Promise<TransactionSignature> {
2622
- const bank = this.getBankAccount(bankIndex);
3285
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2623
3286
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2624
3287
  this.program.programId,
2625
3288
  this.wallet.publicKey,
2626
- bankIndex
3289
+ marketIndex
2627
3290
  );
2628
3291
 
2629
3292
  const remainingAccounts = this.getRemainingAccounts({
2630
- writableBankIndex: bankIndex,
3293
+ writableSpotMarketIndex: marketIndex,
2631
3294
  });
2632
3295
 
2633
3296
  return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(
2634
- bankIndex,
3297
+ marketIndex,
2635
3298
  {
2636
3299
  accounts: {
2637
3300
  state: await this.getStatePublicKey(),
2638
- bank: bank.pubkey,
3301
+ spotMarket: spotMarketAccount.pubkey,
2639
3302
  insuranceFundStake: ifStakeAccountPublicKey,
2640
3303
  userStats: this.getUserStatsAccountPublicKey(),
2641
3304
  authority: this.wallet.publicKey,
2642
- insuranceFundVault: bank.insuranceFundVault,
3305
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2643
3306
  // userTokenAccount: collateralAccountPublicKey,
2644
3307
  // tokenProgram: TOKEN_PROGRAM_ID,
2645
3308
  },
@@ -2649,28 +3312,28 @@ export class ClearingHouse {
2649
3312
  }
2650
3313
 
2651
3314
  public async removeInsuranceFundStake(
2652
- bankIndex: BN,
3315
+ marketIndex: BN,
2653
3316
  collateralAccountPublicKey: PublicKey
2654
3317
  ): Promise<TransactionSignature> {
2655
- const bank = this.getBankAccount(bankIndex);
3318
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2656
3319
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2657
3320
  this.program.programId,
2658
3321
  this.wallet.publicKey,
2659
- bankIndex
3322
+ marketIndex
2660
3323
  );
2661
3324
 
2662
3325
  const remainingAccounts = this.getRemainingAccounts({
2663
- writableBankIndex: bankIndex,
3326
+ writableSpotMarketIndex: marketIndex,
2664
3327
  });
2665
3328
 
2666
- return await this.program.rpc.removeInsuranceFundStake(bankIndex, {
3329
+ return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
2667
3330
  accounts: {
2668
3331
  state: await this.getStatePublicKey(),
2669
- bank: bank.pubkey,
3332
+ spotMarket: spotMarketAccount.pubkey,
2670
3333
  insuranceFundStake: ifStakeAccountPublicKey,
2671
3334
  userStats: this.getUserStatsAccountPublicKey(),
2672
3335
  authority: this.wallet.publicKey,
2673
- insuranceFundVault: bank.insuranceFundVault,
3336
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2674
3337
  clearingHouseSigner: this.getSignerPublicKey(),
2675
3338
  userTokenAccount: collateralAccountPublicKey,
2676
3339
  tokenProgram: TOKEN_PROGRAM_ID,
@@ -2680,24 +3343,66 @@ export class ClearingHouse {
2680
3343
  }
2681
3344
 
2682
3345
  public async settleRevenueToInsuranceFund(
2683
- bankIndex: BN
3346
+ marketIndex: BN
2684
3347
  ): Promise<TransactionSignature> {
2685
- const bank = this.getBankAccount(bankIndex);
3348
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2686
3349
 
2687
3350
  const remainingAccounts = this.getRemainingAccounts({
2688
- writableBankIndex: bankIndex,
3351
+ writableSpotMarketIndex: marketIndex,
2689
3352
  });
2690
3353
 
2691
- return await this.program.rpc.settleRevenueToInsuranceFund(bankIndex, {
3354
+ return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
2692
3355
  accounts: {
2693
3356
  state: await this.getStatePublicKey(),
2694
- bank: bank.pubkey,
2695
- bankVault: bank.vault,
3357
+ spotMarket: spotMarketAccount.pubkey,
3358
+ spotMarketVault: spotMarketAccount.vault,
2696
3359
  clearingHouseSigner: this.getSignerPublicKey(),
2697
- insuranceFundVault: bank.insuranceFundVault,
3360
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2698
3361
  tokenProgram: TOKEN_PROGRAM_ID,
2699
3362
  },
2700
3363
  remainingAccounts,
2701
3364
  });
2702
3365
  }
3366
+
3367
+ public async resolvePerpPnlDeficit(
3368
+ spotMarketIndex: BN,
3369
+ perpMarketIndex: BN
3370
+ ): Promise<TransactionSignature> {
3371
+ const { txSig } = await this.txSender.send(
3372
+ wrapInTx(
3373
+ await this.getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex)
3374
+ ),
3375
+ [],
3376
+ this.opts
3377
+ );
3378
+ return txSig;
3379
+ }
3380
+
3381
+ public async getResolvePerpPnlDeficitIx(
3382
+ spotMarketIndex: BN,
3383
+ perpMarketIndex: BN
3384
+ ): Promise<TransactionInstruction> {
3385
+ const remainingAccounts = this.getRemainingAccounts({
3386
+ writablePerpMarketIndex: perpMarketIndex,
3387
+ writableSpotMarketIndex: spotMarketIndex,
3388
+ });
3389
+
3390
+ const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
3391
+
3392
+ return await this.program.instruction.resolvePerpPnlDeficit(
3393
+ spotMarketIndex,
3394
+ perpMarketIndex,
3395
+ {
3396
+ accounts: {
3397
+ state: await this.getStatePublicKey(),
3398
+ authority: this.wallet.publicKey,
3399
+ spotMarketVault: spotMarket.vault,
3400
+ insuranceFundVault: spotMarket.insuranceFundVault,
3401
+ clearingHouseSigner: this.getSignerPublicKey(),
3402
+ tokenProgram: TOKEN_PROGRAM_ID,
3403
+ },
3404
+ remainingAccounts: remainingAccounts,
3405
+ }
3406
+ );
3407
+ }
2703
3408
  }