@drift-labs/sdk 0.2.0-master.24 → 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 (193) 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 +8 -6
  7. package/lib/addresses/pda.js +35 -27
  8. package/lib/admin.d.ts +9 -6
  9. package/lib/admin.js +90 -54
  10. package/lib/clearingHouse.d.ts +71 -42
  11. package/lib/clearingHouse.js +765 -282
  12. package/lib/clearingHouseConfig.d.ts +2 -2
  13. package/lib/clearingHouseUser.d.ts +19 -17
  14. package/lib/clearingHouseUser.js +145 -123
  15. package/lib/config.d.ts +7 -7
  16. package/lib/config.js +21 -21
  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/eventSubscriber.d.ts +4 -2
  24. package/lib/events/eventSubscriber.js +16 -9
  25. package/lib/events/fetchLogs.d.ts +10 -1
  26. package/lib/events/fetchLogs.js +27 -7
  27. package/lib/events/pollingLogProvider.d.ts +2 -1
  28. package/lib/events/pollingLogProvider.js +6 -2
  29. package/lib/events/types.d.ts +4 -2
  30. package/lib/events/types.js +2 -0
  31. package/lib/examples/makeTradeExample.js +18 -6
  32. package/lib/idl/clearing_house.json +1128 -347
  33. package/lib/index.d.ts +6 -3
  34. package/lib/index.js +6 -3
  35. package/lib/math/amm.d.ts +5 -3
  36. package/lib/math/amm.js +42 -4
  37. package/lib/math/funding.d.ts +6 -6
  38. package/lib/math/funding.js +2 -1
  39. package/lib/math/margin.d.ts +4 -4
  40. package/lib/math/margin.js +18 -11
  41. package/lib/math/market.d.ts +10 -9
  42. package/lib/math/market.js +29 -6
  43. package/lib/math/oracles.d.ts +2 -1
  44. package/lib/math/oracles.js +11 -1
  45. package/lib/math/orders.d.ts +5 -5
  46. package/lib/math/position.d.ts +13 -13
  47. package/lib/math/position.js +19 -19
  48. package/lib/math/spotBalance.d.ts +19 -0
  49. package/lib/math/spotBalance.js +176 -0
  50. package/lib/math/spotMarket.d.ts +4 -0
  51. package/lib/math/spotMarket.js +8 -0
  52. package/lib/math/spotPosition.d.ts +2 -0
  53. package/lib/math/spotPosition.js +8 -0
  54. package/lib/math/state.js +2 -2
  55. package/lib/math/trade.d.ts +4 -4
  56. package/lib/orderParams.d.ts +4 -4
  57. package/lib/orderParams.js +12 -4
  58. package/lib/serum/serumSubscriber.d.ts +23 -0
  59. package/lib/serum/serumSubscriber.js +41 -0
  60. package/lib/serum/types.d.ts +11 -0
  61. package/lib/serum/types.js +2 -0
  62. package/lib/tx/retryTxSender.d.ts +1 -1
  63. package/lib/tx/retryTxSender.js +4 -2
  64. package/lib/tx/types.d.ts +1 -1
  65. package/lib/types.d.ts +148 -39
  66. package/lib/types.js +37 -9
  67. package/my-script/.env +7 -0
  68. package/my-script/getUserStats.ts +106 -0
  69. package/my-script/multiConnections.ts +119 -0
  70. package/my-script/test-regex.ts +11 -0
  71. package/my-script/utils.ts +52 -0
  72. package/package.json +1 -1
  73. package/src/accounts/bulkAccountLoader.js +249 -0
  74. package/src/accounts/bulkUserStatsSubscription.js +75 -0
  75. package/src/accounts/bulkUserSubscription.js +75 -0
  76. package/src/accounts/fetch.js +92 -0
  77. package/src/accounts/pollingClearingHouseAccountSubscriber.js +465 -0
  78. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +38 -38
  79. package/src/accounts/pollingOracleSubscriber.js +156 -0
  80. package/src/accounts/pollingTokenAccountSubscriber.js +141 -0
  81. package/src/accounts/pollingUserAccountSubscriber.js +208 -0
  82. package/src/accounts/pollingUserStatsAccountSubscriber.js +208 -0
  83. package/src/accounts/types.js +28 -0
  84. package/src/accounts/types.ts +11 -9
  85. package/src/accounts/utils.js +7 -0
  86. package/src/accounts/webSocketAccountSubscriber.js +138 -0
  87. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +433 -0
  88. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +59 -52
  89. package/src/accounts/webSocketUserAccountSubscriber.js +113 -0
  90. package/src/accounts/webSocketUserStatsAccountSubsriber.js +113 -0
  91. package/src/addresses/pda.js +186 -0
  92. package/src/addresses/pda.ts +56 -42
  93. package/src/admin.js +1284 -0
  94. package/src/admin.ts +149 -75
  95. package/src/assert/assert.js +1 -1
  96. package/src/clearingHouse.js +3433 -0
  97. package/src/clearingHouse.ts +1097 -380
  98. package/src/clearingHouseConfig.js +2 -0
  99. package/src/clearingHouseConfig.ts +2 -2
  100. package/src/clearingHouseUser.js +874 -0
  101. package/src/clearingHouseUser.ts +237 -172
  102. package/src/clearingHouseUserConfig.js +2 -0
  103. package/src/clearingHouseUserStats.js +115 -0
  104. package/src/clearingHouseUserStatsConfig.js +2 -0
  105. package/src/config.js +80 -0
  106. package/src/config.ts +30 -30
  107. package/src/constants/numericConstants.js +18 -11
  108. package/src/constants/numericConstants.ts +17 -15
  109. package/{lib/constants/markets.js → src/constants/perpMarkets.js} +11 -11
  110. package/src/constants/{markets.ts → perpMarkets.ts} +5 -5
  111. package/src/constants/spotMarkets.js +51 -0
  112. package/src/constants/{banks.ts → spotMarkets.ts} +19 -19
  113. package/src/events/eventList.js +66 -23
  114. package/src/events/eventSubscriber.js +202 -0
  115. package/src/events/eventSubscriber.ts +20 -12
  116. package/src/events/fetchLogs.js +117 -0
  117. package/src/events/fetchLogs.ts +35 -8
  118. package/src/events/pollingLogProvider.js +113 -0
  119. package/src/events/pollingLogProvider.ts +10 -2
  120. package/src/events/sort.js +41 -0
  121. package/src/events/txEventCache.js +22 -19
  122. package/src/events/types.js +25 -0
  123. package/src/events/types.ts +7 -1
  124. package/src/events/webSocketLogProvider.js +76 -0
  125. package/src/examples/makeTradeExample.ts +27 -6
  126. package/src/factory/bigNum.js +183 -180
  127. package/src/factory/oracleClient.js +9 -9
  128. package/src/idl/clearing_house.json +1128 -347
  129. package/src/index.js +75 -0
  130. package/src/index.ts +6 -3
  131. package/src/math/amm.js +422 -0
  132. package/src/math/amm.ts +73 -5
  133. package/src/math/auction.js +10 -10
  134. package/src/math/conversion.js +4 -3
  135. package/src/math/funding.js +223 -175
  136. package/src/math/funding.ts +7 -7
  137. package/src/math/insurance.js +27 -0
  138. package/src/math/margin.js +77 -0
  139. package/src/math/margin.ts +34 -23
  140. package/src/math/market.js +105 -0
  141. package/src/math/market.ts +71 -19
  142. package/src/math/oracles.js +40 -10
  143. package/src/math/oracles.ts +18 -1
  144. package/src/math/orders.js +153 -0
  145. package/src/math/orders.ts +5 -5
  146. package/src/math/position.js +172 -0
  147. package/src/math/position.ts +31 -31
  148. package/src/math/repeg.js +40 -40
  149. package/src/math/spotBalance.js +176 -0
  150. package/src/math/spotBalance.ts +290 -0
  151. package/src/math/spotMarket.js +8 -0
  152. package/src/math/spotMarket.ts +9 -0
  153. package/src/math/spotPosition.js +8 -0
  154. package/src/math/spotPosition.ts +6 -0
  155. package/src/math/state.ts +2 -2
  156. package/src/math/trade.js +81 -74
  157. package/src/math/trade.ts +4 -4
  158. package/src/math/utils.js +8 -7
  159. package/src/oracles/oracleClientCache.js +10 -9
  160. package/src/oracles/pythClient.js +52 -17
  161. package/src/oracles/quoteAssetOracleClient.js +44 -13
  162. package/src/oracles/switchboardClient.js +69 -37
  163. package/src/oracles/types.js +1 -1
  164. package/src/orderParams.js +14 -6
  165. package/src/orderParams.ts +16 -8
  166. package/src/serum/serumSubscriber.js +102 -0
  167. package/src/serum/serumSubscriber.ts +80 -0
  168. package/src/serum/types.js +2 -0
  169. package/src/serum/types.ts +13 -0
  170. package/src/slot/SlotSubscriber.js +67 -20
  171. package/src/token/index.js +4 -4
  172. package/src/tokenFaucet.js +288 -154
  173. package/src/tx/retryTxSender.js +280 -0
  174. package/src/tx/retryTxSender.ts +5 -2
  175. package/src/tx/types.js +1 -1
  176. package/src/tx/types.ts +2 -1
  177. package/src/tx/utils.js +7 -6
  178. package/src/types.js +216 -0
  179. package/src/types.ts +131 -39
  180. package/src/userName.js +5 -5
  181. package/src/util/computeUnits.js +46 -11
  182. package/src/util/promiseTimeout.js +5 -5
  183. package/src/util/tps.js +46 -12
  184. package/src/wallet.js +55 -18
  185. package/lib/math/bankBalance.d.ts +0 -15
  186. package/lib/math/bankBalance.js +0 -150
  187. package/src/addresses/marketAddresses.js +0 -26
  188. package/src/constants/banks.js +0 -42
  189. package/src/examples/makeTradeExample.js +0 -80
  190. package/src/math/bankBalance.ts +0 -258
  191. package/src/math/state.js +0 -15
  192. package/src/math/utils.js.map +0 -1
  193. 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';
@@ -39,9 +41,12 @@ import { TokenFaucet } from './tokenFaucet';
39
41
  import { EventEmitter } from 'events';
40
42
  import StrictEventEmitter from 'strict-event-emitter-types';
41
43
  import {
44
+ getClearingHouseSignerPublicKey,
42
45
  getClearingHouseStateAccountPublicKey,
43
46
  getInsuranceFundStakeAccountPublicKey,
44
47
  getMarketPublicKey,
48
+ getSerumFulfillmentConfigPublicKey,
49
+ getSerumSignerPublicKey,
45
50
  getUserAccountPublicKey,
46
51
  getUserAccountPublicKeySync,
47
52
  getUserStatsAccountPublicKey,
@@ -55,11 +60,11 @@ import { TxSender } from './tx/types';
55
60
  import { wrapInTx } from './tx/utils';
56
61
  import {
57
62
  ONE,
58
- QUOTE_ASSET_BANK_INDEX,
63
+ QUOTE_SPOT_MARKET_INDEX,
59
64
  ZERO,
60
65
  } from './constants/numericConstants';
61
66
  import { findDirectionToClose, positionIsAvailable } from './math/position';
62
- import { getTokenAmount } from './math/bankBalance';
67
+ import { getTokenAmount } from './math/spotBalance';
63
68
  import { DEFAULT_USER_NAME, encodeName } from './userName';
64
69
  import { OraclePriceData } from './oracles/types';
65
70
  import { ClearingHouseConfig } from './clearingHouseConfig';
@@ -68,9 +73,10 @@ import { WebSocketClearingHouseAccountSubscriber } from './accounts/webSocketCle
68
73
  import { RetryTxSender } from './tx/retryTxSender';
69
74
  import { ClearingHouseUser } from './clearingHouseUser';
70
75
  import { ClearingHouseUserAccountSubscriptionConfig } from './clearingHouseUserConfig';
71
- import { getMarketsBanksAndOraclesForSubscription } from './config';
72
- import { WRAPPED_SOL_MINT } from './constants/banks';
76
+ import { getMarketsAndOraclesForSubscription } from './config';
77
+ import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
73
78
  import { ClearingHouseUserStats } from './clearingHouseUserStats';
79
+ import { isSpotPositionAvailable } from './math/spotPosition';
74
80
 
75
81
  /**
76
82
  * # ClearingHouse
@@ -138,17 +144,21 @@ export class ClearingHouse {
138
144
  });
139
145
  }
140
146
 
141
- let marketIndexes = config.marketIndexes;
142
- let bankIndexes = config.bankIndexes;
147
+ let perpMarketIndexes = config.perpMarketIndexes;
148
+ let spotMarketIndexes = config.spotMarketIndexes;
143
149
  let oracleInfos = config.oracleInfos;
144
150
  if (config.env) {
145
151
  const {
146
- marketIndexes: envMarketIndexes,
147
- bankIndexes: envBankIndexes,
152
+ perpMarketIndexes: envPerpMarketIndexes,
153
+ spotMarketIndexes: envSpotMarketIndexes,
148
154
  oracleInfos: envOralceInfos,
149
- } = getMarketsBanksAndOraclesForSubscription(config.env);
150
- marketIndexes = marketIndexes ? marketIndexes : envMarketIndexes;
151
- bankIndexes = bankIndexes ? bankIndexes : envBankIndexes;
155
+ } = getMarketsAndOraclesForSubscription(config.env);
156
+ perpMarketIndexes = perpMarketIndexes
157
+ ? perpMarketIndexes
158
+ : envPerpMarketIndexes;
159
+ spotMarketIndexes = spotMarketIndexes
160
+ ? spotMarketIndexes
161
+ : envSpotMarketIndexes;
152
162
  oracleInfos = oracleInfos ? oracleInfos : envOralceInfos;
153
163
  }
154
164
 
@@ -156,15 +166,15 @@ export class ClearingHouse {
156
166
  this.accountSubscriber = new PollingClearingHouseAccountSubscriber(
157
167
  this.program,
158
168
  config.accountSubscription.accountLoader,
159
- marketIndexes ?? [],
160
- bankIndexes ?? [],
169
+ perpMarketIndexes ?? [],
170
+ spotMarketIndexes ?? [],
161
171
  oracleInfos ?? []
162
172
  );
163
173
  } else {
164
174
  this.accountSubscriber = new WebSocketClearingHouseAccountSubscriber(
165
175
  this.program,
166
- config.marketIndexes ?? [],
167
- config.bankIndexes ?? [],
176
+ config.perpMarketIndexes ?? [],
177
+ config.spotMarketIndexes ?? [],
168
178
  config.oracleInfos ?? []
169
179
  );
170
180
  }
@@ -260,29 +270,45 @@ export class ClearingHouse {
260
270
  return this.statePublicKey;
261
271
  }
262
272
 
273
+ signerPublicKey?: PublicKey;
274
+ public getSignerPublicKey(): PublicKey {
275
+ if (this.signerPublicKey) {
276
+ return this.signerPublicKey;
277
+ }
278
+ this.signerPublicKey = getClearingHouseSignerPublicKey(
279
+ this.program.programId
280
+ );
281
+ return this.signerPublicKey;
282
+ }
283
+
263
284
  public getStateAccount(): StateAccount {
264
285
  return this.accountSubscriber.getStateAccountAndSlot().data;
265
286
  }
266
287
 
267
- public getMarketAccount(marketIndex: BN | number): MarketAccount | undefined {
288
+ public getPerpMarketAccount(
289
+ marketIndex: BN | number
290
+ ): PerpMarketAccount | undefined {
268
291
  marketIndex = marketIndex instanceof BN ? marketIndex : new BN(marketIndex);
269
292
  return this.accountSubscriber.getMarketAccountAndSlot(marketIndex)?.data;
270
293
  }
271
294
 
272
- public getMarketAccounts(): MarketAccount[] {
295
+ public getPerpMarketAccounts(): PerpMarketAccount[] {
273
296
  return this.accountSubscriber
274
297
  .getMarketAccountsAndSlots()
275
298
  .map((value) => value.data);
276
299
  }
277
300
 
278
- public getBankAccount(bankIndex: BN | number): BankAccount | undefined {
279
- bankIndex = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
280
- 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;
281
306
  }
282
307
 
283
- public getQuoteAssetBankAccount(): BankAccount {
284
- return this.accountSubscriber.getBankAccountAndSlot(QUOTE_ASSET_BANK_INDEX)
285
- .data;
308
+ public getQuoteSpotMarketAccount(): SpotMarketAccount {
309
+ return this.accountSubscriber.getSpotMarketAccountAndSlot(
310
+ QUOTE_SPOT_MARKET_INDEX
311
+ ).data;
286
312
  }
287
313
 
288
314
  public getOraclePriceDataAndSlot(
@@ -291,6 +317,18 @@ export class ClearingHouse {
291
317
  return this.accountSubscriber.getOraclePriceDataAndSlot(oraclePublicKey);
292
318
  }
293
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
+
294
332
  /**
295
333
  * Update the wallet to use for clearing house transactions and linked user account
296
334
  * @param newWallet
@@ -421,6 +459,19 @@ export class ClearingHouse {
421
459
  });
422
460
  }
423
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
+
424
475
  public getUser(userId?: number): ClearingHouseUser {
425
476
  userId = userId ?? this.activeUserId;
426
477
  if (!this.users.has(userId)) {
@@ -464,29 +515,29 @@ export class ClearingHouse {
464
515
  return this.getUser(userId).getUserAccountAndSlot();
465
516
  }
466
517
 
467
- public getUserBankBalance(
468
- bankIndex: number | BN
469
- ): UserBankBalance | undefined {
470
- const bankIndexBN = bankIndex instanceof BN ? bankIndex : new BN(bankIndex);
471
- return this.getUserAccount().bankBalances.find((bankBalance) =>
472
- 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)
473
523
  );
474
524
  }
475
525
 
476
526
  public getQuoteAssetTokenAmount(): BN {
477
- const bank = this.getBankAccount(QUOTE_ASSET_BANK_INDEX);
478
- 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);
479
529
  return getTokenAmount(
480
- userBankBalance.balance,
481
- bank,
482
- userBankBalance.balanceType
530
+ spotPosition.balance,
531
+ spotMarket,
532
+ spotPosition.balanceType
483
533
  );
484
534
  }
485
535
 
486
536
  getRemainingAccounts(params: {
487
- writableMarketIndex?: BN;
488
- writableBankIndex?: BN;
489
- readableMarketIndex?: BN;
537
+ writablePerpMarketIndex?: BN;
538
+ writableSpotMarketIndex?: BN;
539
+ readablePerpMarketIndex?: BN;
540
+ readableSpotMarketIndex?: BN;
490
541
  }): AccountMeta[] {
491
542
  const userAccountAndSlot = this.getUserAccountAndSlot();
492
543
  if (!userAccountAndSlot) {
@@ -498,14 +549,14 @@ export class ClearingHouse {
498
549
  userAccountAndSlot;
499
550
 
500
551
  const oracleAccountMap = new Map<string, AccountMeta>();
501
- const bankAccountMap = new Map<number, AccountMeta>();
502
- const marketAccountMap = new Map<number, AccountMeta>();
552
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
553
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
503
554
  for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
504
555
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
505
556
  // otherwise remove from slot
506
557
  if (slot > lastUserPositionsSlot) {
507
- const marketAccount = this.getMarketAccount(marketIndexNum);
508
- marketAccountMap.set(marketIndexNum, {
558
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
559
+ perpMarketAccountMap.set(marketIndexNum, {
509
560
  pubkey: marketAccount.pubkey,
510
561
  isSigner: false,
511
562
  isWritable: false,
@@ -520,11 +571,11 @@ export class ClearingHouse {
520
571
  }
521
572
  }
522
573
 
523
- for (const position of userAccount.positions) {
574
+ for (const position of userAccount.perpPositions) {
524
575
  if (!positionIsAvailable(position)) {
525
576
  const marketIndexNum = position.marketIndex.toNumber();
526
- const marketAccount = this.getMarketAccount(marketIndexNum);
527
- marketAccountMap.set(marketIndexNum, {
577
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
578
+ perpMarketAccountMap.set(marketIndexNum, {
528
579
  pubkey: marketAccount.pubkey,
529
580
  isSigner: false,
530
581
  isWritable: false,
@@ -537,11 +588,11 @@ export class ClearingHouse {
537
588
  }
538
589
  }
539
590
 
540
- if (params.readableMarketIndex) {
541
- const marketAccount = this.getMarketAccount(
542
- params.readableMarketIndex.toNumber()
591
+ if (params.readablePerpMarketIndex) {
592
+ const marketAccount = this.getPerpMarketAccount(
593
+ params.readablePerpMarketIndex.toNumber()
543
594
  );
544
- marketAccountMap.set(params.readableMarketIndex.toNumber(), {
595
+ perpMarketAccountMap.set(params.readablePerpMarketIndex.toNumber(), {
545
596
  pubkey: marketAccount.pubkey,
546
597
  isSigner: false,
547
598
  isWritable: true,
@@ -553,11 +604,11 @@ export class ClearingHouse {
553
604
  });
554
605
  }
555
606
 
556
- if (params.writableMarketIndex) {
557
- const marketAccount = this.getMarketAccount(
558
- params.writableMarketIndex.toNumber()
607
+ if (params.writablePerpMarketIndex) {
608
+ const marketAccount = this.getPerpMarketAccount(
609
+ params.writablePerpMarketIndex.toNumber()
559
610
  );
560
- marketAccountMap.set(params.writableMarketIndex.toNumber(), {
611
+ perpMarketAccountMap.set(params.writablePerpMarketIndex.toNumber(), {
561
612
  pubkey: marketAccount.pubkey,
562
613
  isSigner: false,
563
614
  isWritable: true,
@@ -569,17 +620,19 @@ export class ClearingHouse {
569
620
  });
570
621
  }
571
622
 
572
- for (const userBankBalance of userAccount.bankBalances) {
573
- if (!userBankBalance.balance.eq(ZERO)) {
574
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
575
- bankAccountMap.set(userBankBalance.bankIndex.toNumber(), {
576
- 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,
577
630
  isSigner: false,
578
631
  isWritable: false,
579
632
  });
580
- if (!bankAccount.bankIndex.eq(ZERO)) {
581
- oracleAccountMap.set(bankAccount.oracle.toString(), {
582
- pubkey: bankAccount.oracle,
633
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
634
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
635
+ pubkey: spotMarketAccount.oracle,
583
636
  isSigner: false,
584
637
  isWritable: false,
585
638
  });
@@ -587,16 +640,36 @@ export class ClearingHouse {
587
640
  }
588
641
  }
589
642
 
590
- if (params.writableBankIndex) {
591
- const bankAccount = this.getBankAccount(params.writableBankIndex);
592
- bankAccountMap.set(params.writableBankIndex.toNumber(), {
593
- 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,
594
667
  isSigner: false,
595
668
  isWritable: true,
596
669
  });
597
- if (!bankAccount.bankIndex.eq(ZERO)) {
598
- oracleAccountMap.set(bankAccount.oracle.toString(), {
599
- pubkey: bankAccount.oracle,
670
+ if (!spotMarketAccount.marketIndex.eq(ZERO)) {
671
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
672
+ pubkey: spotMarketAccount.oracle,
600
673
  isSigner: false,
601
674
  isWritable: false,
602
675
  });
@@ -605,8 +678,8 @@ export class ClearingHouse {
605
678
 
606
679
  return [
607
680
  ...oracleAccountMap.values(),
608
- ...bankAccountMap.values(),
609
- ...marketAccountMap.values(),
681
+ ...spotMarketAccountMap.values(),
682
+ ...perpMarketAccountMap.values(),
610
683
  ];
611
684
  }
612
685
 
@@ -625,7 +698,7 @@ export class ClearingHouse {
625
698
 
626
699
  public async deposit(
627
700
  amount: BN,
628
- bankIndex: BN,
701
+ marketIndex: BN,
629
702
  collateralAccountPublicKey: PublicKey,
630
703
  userId?: number,
631
704
  reduceOnly = false
@@ -633,14 +706,14 @@ export class ClearingHouse {
633
706
  const tx = new Transaction();
634
707
  const additionalSigners: Array<Signer> = [];
635
708
 
636
- const bank = this.getBankAccount(bankIndex);
709
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
637
710
 
638
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
711
+ const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
639
712
 
640
713
  const authority = this.wallet.publicKey;
641
714
 
642
715
  const createWSOLTokenAccount =
643
- isSolBank && collateralAccountPublicKey.equals(authority);
716
+ isSolMarket && collateralAccountPublicKey.equals(authority);
644
717
 
645
718
  if (createWSOLTokenAccount) {
646
719
  const { ixs, signers, pubkey } =
@@ -657,7 +730,7 @@ export class ClearingHouse {
657
730
 
658
731
  const depositCollateralIx = await this.getDepositInstruction(
659
732
  amount,
660
- bankIndex,
733
+ marketIndex,
661
734
  collateralAccountPublicKey,
662
735
  userId,
663
736
  reduceOnly,
@@ -689,7 +762,7 @@ export class ClearingHouse {
689
762
 
690
763
  async getDepositInstruction(
691
764
  amount: BN,
692
- bankIndex: BN,
765
+ marketIndex: BN,
693
766
  userTokenAccount: PublicKey,
694
767
  userId?: number,
695
768
  reduceOnly = false,
@@ -706,35 +779,35 @@ export class ClearingHouse {
706
779
  let remainingAccounts = [];
707
780
  if (userInitialized) {
708
781
  remainingAccounts = this.getRemainingAccounts({
709
- writableBankIndex: bankIndex,
782
+ writableSpotMarketIndex: marketIndex,
710
783
  });
711
784
  } else {
712
- const bankAccount = this.getBankAccount(bankIndex);
713
- if (!bankAccount.oracle.equals(PublicKey.default)) {
785
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
786
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
714
787
  remainingAccounts.push({
715
- pubkey: bankAccount.oracle,
788
+ pubkey: spotMarketAccount.oracle,
716
789
  isSigner: false,
717
790
  isWritable: false,
718
791
  });
719
792
  }
720
793
  remainingAccounts.push({
721
- pubkey: bankAccount.pubkey,
794
+ pubkey: spotMarketAccount.pubkey,
722
795
  isSigner: false,
723
796
  isWritable: true,
724
797
  });
725
798
  }
726
799
 
727
- const bank = this.getBankAccount(bankIndex);
800
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
728
801
 
729
802
  return await this.program.instruction.deposit(
730
- bankIndex,
803
+ marketIndex,
731
804
  amount,
732
805
  reduceOnly,
733
806
  {
734
807
  accounts: {
735
808
  state: await this.getStatePublicKey(),
736
- bank: bank.pubkey,
737
- bankVault: bank.vault,
809
+ spotMarket: spotMarketAccount.pubkey,
810
+ spotMarketVault: spotMarketAccount.vault,
738
811
  user: userAccountPublicKey,
739
812
  userStats: this.getUserStatsAccountPublicKey(),
740
813
  userTokenAccount: userTokenAccount,
@@ -757,7 +830,7 @@ export class ClearingHouse {
757
830
  }
758
831
 
759
832
  private async getSolWithdrawalIxs(
760
- bankIndex: BN,
833
+ marketIndex: BN,
761
834
  amount: BN
762
835
  ): Promise<{
763
836
  ixs: anchor.web3.TransactionInstruction[];
@@ -789,7 +862,7 @@ export class ClearingHouse {
789
862
 
790
863
  const withdrawIx = await this.getWithdrawIx(
791
864
  amount,
792
- bankIndex,
865
+ marketIndex,
793
866
  pubkey,
794
867
  true
795
868
  );
@@ -856,7 +929,7 @@ export class ClearingHouse {
856
929
  * Creates the Clearing House User account for a user, and deposits some initial collateral
857
930
  * @param amount
858
931
  * @param userTokenAccount
859
- * @param bankIndex
932
+ * @param marketIndex
860
933
  * @param userId
861
934
  * @param name
862
935
  * @param fromUserId
@@ -865,7 +938,7 @@ export class ClearingHouse {
865
938
  public async initializeUserAccountAndDepositCollateral(
866
939
  amount: BN,
867
940
  userTokenAccount: PublicKey,
868
- bankIndex = new BN(0),
941
+ marketIndex = new BN(0),
869
942
  userId = 0,
870
943
  name = DEFAULT_USER_NAME,
871
944
  fromUserId?: number,
@@ -876,16 +949,16 @@ export class ClearingHouse {
876
949
 
877
950
  const additionalSigners: Array<Signer> = [];
878
951
 
879
- const bank = this.getBankAccount(bankIndex);
952
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
880
953
 
881
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
954
+ const isSolMarket = spotMarket.mint.equals(WRAPPED_SOL_MINT);
882
955
 
883
956
  const tx = new Transaction();
884
957
 
885
958
  const authority = this.wallet.publicKey;
886
959
 
887
960
  const createWSOLTokenAccount =
888
- isSolBank && userTokenAccount.equals(authority);
961
+ isSolMarket && userTokenAccount.equals(authority);
889
962
 
890
963
  if (createWSOLTokenAccount) {
891
964
  const {
@@ -905,10 +978,15 @@ export class ClearingHouse {
905
978
 
906
979
  const depositCollateralIx =
907
980
  fromUserId != null
908
- ? await this.getTransferDepositIx(amount, bankIndex, fromUserId, userId)
981
+ ? await this.getTransferDepositIx(
982
+ amount,
983
+ marketIndex,
984
+ fromUserId,
985
+ userId
986
+ )
909
987
  : await this.getDepositInstruction(
910
988
  amount,
911
- bankIndex,
989
+ marketIndex,
912
990
  userTokenAccount,
913
991
  userId,
914
992
  false,
@@ -945,7 +1023,7 @@ export class ClearingHouse {
945
1023
  public async initializeUserAccountForDevnet(
946
1024
  userId = 0,
947
1025
  name = DEFAULT_USER_NAME,
948
- bankIndex: BN,
1026
+ marketIndex: BN,
949
1027
  tokenFaucet: TokenFaucet,
950
1028
  amount: BN,
951
1029
  referrerInfo?: ReferrerInfo
@@ -961,7 +1039,7 @@ export class ClearingHouse {
961
1039
 
962
1040
  const depositCollateralIx = await this.getDepositInstruction(
963
1041
  amount,
964
- bankIndex,
1042
+ marketIndex,
965
1043
  associateTokenPublicKey,
966
1044
  userId,
967
1045
  false,
@@ -982,21 +1060,21 @@ export class ClearingHouse {
982
1060
 
983
1061
  public async withdraw(
984
1062
  amount: BN,
985
- bankIndex: BN,
1063
+ marketIndex: BN,
986
1064
  userTokenAccount: PublicKey,
987
1065
  reduceOnly = false
988
1066
  ): Promise<TransactionSignature> {
989
1067
  const tx = new Transaction();
990
1068
  const additionalSigners: Array<Signer> = [];
991
1069
 
992
- const bank = this.getBankAccount(bankIndex);
1070
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
993
1071
 
994
- const isSolBank = bank.mint.equals(WRAPPED_SOL_MINT);
1072
+ const isSolMarket = spotMarketAccount.mint.equals(WRAPPED_SOL_MINT);
995
1073
 
996
1074
  const authority = this.wallet.publicKey;
997
1075
 
998
1076
  const createWSOLTokenAccount =
999
- isSolBank && userTokenAccount.equals(authority);
1077
+ isSolMarket && userTokenAccount.equals(authority);
1000
1078
 
1001
1079
  if (createWSOLTokenAccount) {
1002
1080
  const { ixs, signers, pubkey } =
@@ -1013,7 +1091,7 @@ export class ClearingHouse {
1013
1091
 
1014
1092
  const withdrawCollateral = await this.getWithdrawIx(
1015
1093
  amount,
1016
- bank.bankIndex,
1094
+ spotMarketAccount.marketIndex,
1017
1095
  userTokenAccount,
1018
1096
  reduceOnly
1019
1097
  );
@@ -1043,28 +1121,28 @@ export class ClearingHouse {
1043
1121
 
1044
1122
  public async getWithdrawIx(
1045
1123
  amount: BN,
1046
- bankIndex: BN,
1124
+ marketIndex: BN,
1047
1125
  userTokenAccount: PublicKey,
1048
1126
  reduceOnly = false
1049
1127
  ): Promise<TransactionInstruction> {
1050
1128
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1051
1129
 
1052
1130
  const remainingAccounts = this.getRemainingAccounts({
1053
- writableBankIndex: bankIndex,
1131
+ writableSpotMarketIndex: marketIndex,
1054
1132
  });
1055
1133
 
1056
- const bank = this.getBankAccount(bankIndex);
1134
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1057
1135
 
1058
1136
  return await this.program.instruction.withdraw(
1059
- bankIndex,
1137
+ marketIndex,
1060
1138
  amount,
1061
1139
  reduceOnly,
1062
1140
  {
1063
1141
  accounts: {
1064
1142
  state: await this.getStatePublicKey(),
1065
- bank: bank.pubkey,
1066
- bankVault: bank.vault,
1067
- bankVaultAuthority: bank.vaultAuthority,
1143
+ spotMarket: spotMarketAccount.pubkey,
1144
+ spotMarketVault: spotMarketAccount.vault,
1145
+ clearingHouseSigner: this.getSignerPublicKey(),
1068
1146
  user: userAccountPublicKey,
1069
1147
  userStats: this.getUserStatsAccountPublicKey(),
1070
1148
  userTokenAccount: userTokenAccount,
@@ -1078,13 +1156,18 @@ export class ClearingHouse {
1078
1156
 
1079
1157
  public async transferDeposit(
1080
1158
  amount: BN,
1081
- bankIndex: BN,
1159
+ marketIndex: BN,
1082
1160
  fromUserId: number,
1083
1161
  toUserId: number
1084
1162
  ): Promise<TransactionSignature> {
1085
1163
  const { txSig } = await this.txSender.send(
1086
1164
  wrapInTx(
1087
- await this.getTransferDepositIx(amount, bankIndex, fromUserId, toUserId)
1165
+ await this.getTransferDepositIx(
1166
+ amount,
1167
+ marketIndex,
1168
+ fromUserId,
1169
+ toUserId
1170
+ )
1088
1171
  ),
1089
1172
  [],
1090
1173
  this.opts
@@ -1094,7 +1177,7 @@ export class ClearingHouse {
1094
1177
 
1095
1178
  public async getTransferDepositIx(
1096
1179
  amount: BN,
1097
- bankIndex: BN,
1180
+ marketIndex: BN,
1098
1181
  fromUserId: number,
1099
1182
  toUserId: number
1100
1183
  ): Promise<TransactionInstruction> {
@@ -1110,10 +1193,10 @@ export class ClearingHouse {
1110
1193
  );
1111
1194
 
1112
1195
  const remainingAccounts = this.getRemainingAccounts({
1113
- writableBankIndex: bankIndex,
1196
+ writableSpotMarketIndex: marketIndex,
1114
1197
  });
1115
1198
 
1116
- return await this.program.instruction.transferDeposit(bankIndex, amount, {
1199
+ return await this.program.instruction.transferDeposit(marketIndex, amount, {
1117
1200
  accounts: {
1118
1201
  authority: this.wallet.publicKey,
1119
1202
  fromUser,
@@ -1125,24 +1208,24 @@ export class ClearingHouse {
1125
1208
  });
1126
1209
  }
1127
1210
 
1128
- public async updateBankCumulativeInterest(
1129
- bankIndex: BN
1211
+ public async updateSpotMarketCumulativeInterest(
1212
+ marketIndex: BN
1130
1213
  ): Promise<TransactionSignature> {
1131
1214
  const { txSig } = await this.txSender.send(
1132
- wrapInTx(await this.updateBankCumulativeInterestIx(bankIndex)),
1215
+ wrapInTx(await this.updateSpotMarketCumulativeInterestIx(marketIndex)),
1133
1216
  [],
1134
1217
  this.opts
1135
1218
  );
1136
1219
  return txSig;
1137
1220
  }
1138
1221
 
1139
- public async updateBankCumulativeInterestIx(
1140
- bankIndex: BN
1222
+ public async updateSpotMarketCumulativeInterestIx(
1223
+ marketIndex: BN
1141
1224
  ): Promise<TransactionInstruction> {
1142
- const bank = this.getBankAccount(bankIndex);
1143
- return await this.program.instruction.updateBankCumulativeInterest({
1225
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
1226
+ return await this.program.instruction.updateSpotMarketCumulativeInterest({
1144
1227
  accounts: {
1145
- bank: bank.pubkey,
1228
+ spotMarket: spotMarket.pubkey,
1146
1229
  },
1147
1230
  });
1148
1231
  }
@@ -1166,7 +1249,7 @@ export class ClearingHouse {
1166
1249
  const settleeUserAccount = (await this.program.account.user.fetch(
1167
1250
  settleeUserAccountPublicKey
1168
1251
  )) as UserAccount;
1169
- const userPositions = settleeUserAccount.positions;
1252
+ const userPositions = settleeUserAccount.perpPositions;
1170
1253
  const remainingAccounts = [];
1171
1254
 
1172
1255
  let foundMarket = false;
@@ -1222,15 +1305,15 @@ export class ClearingHouse {
1222
1305
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1223
1306
 
1224
1307
  const remainingAccounts = this.getRemainingAccounts({
1225
- writableMarketIndex: marketIndex,
1308
+ writablePerpMarketIndex: marketIndex,
1226
1309
  });
1227
1310
 
1228
1311
  if (sharesToBurn == undefined) {
1229
1312
  const userAccount = this.getUserAccount();
1230
- const marketPosition = userAccount.positions.filter((position) =>
1313
+ const perpPosition = userAccount.perpPositions.filter((position) =>
1231
1314
  position.marketIndex.eq(marketIndex)
1232
1315
  )[0];
1233
- sharesToBurn = marketPosition.lpShares;
1316
+ sharesToBurn = perpPosition.lpShares;
1234
1317
  console.log('burning lp shares:', sharesToBurn.toString());
1235
1318
  }
1236
1319
 
@@ -1263,7 +1346,7 @@ export class ClearingHouse {
1263
1346
  ): Promise<TransactionInstruction> {
1264
1347
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1265
1348
  const remainingAccounts = this.getRemainingAccounts({
1266
- writableMarketIndex: marketIndex,
1349
+ writablePerpMarketIndex: marketIndex,
1267
1350
  });
1268
1351
 
1269
1352
  return this.program.instruction.addLiquidity(amount, marketIndex, {
@@ -1291,6 +1374,60 @@ export class ClearingHouse {
1291
1374
  });
1292
1375
  }
1293
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
+
1294
1431
  public async placeOrder(
1295
1432
  orderParams: OptionalOrderParams
1296
1433
  ): Promise<TransactionSignature> {
@@ -1303,18 +1440,23 @@ export class ClearingHouse {
1303
1440
  return txSig;
1304
1441
  }
1305
1442
 
1306
- getOrderParams(optionalOrderParams: OptionalOrderParams): OrderParams {
1307
- return Object.assign({}, DefaultOrderParams, optionalOrderParams);
1443
+ getOrderParams(
1444
+ optionalOrderParams: OptionalOrderParams,
1445
+ marketType: MarketType
1446
+ ): OrderParams {
1447
+ return Object.assign({}, DefaultOrderParams, optionalOrderParams, {
1448
+ marketType,
1449
+ });
1308
1450
  }
1309
1451
 
1310
1452
  public async getPlaceOrderIx(
1311
1453
  orderParams: OptionalOrderParams
1312
1454
  ): Promise<TransactionInstruction> {
1313
- orderParams = this.getOrderParams(orderParams);
1455
+ orderParams = this.getOrderParams(orderParams, MarketType.PERP);
1314
1456
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1315
1457
 
1316
1458
  const remainingAccounts = this.getRemainingAccounts({
1317
- readableMarketIndex: orderParams.marketIndex,
1459
+ readablePerpMarketIndex: orderParams.marketIndex,
1318
1460
  });
1319
1461
 
1320
1462
  return await this.program.instruction.placeOrder(orderParams, {
@@ -1347,7 +1489,7 @@ export class ClearingHouse {
1347
1489
  const oracleAccountInfos = [];
1348
1490
  for (const marketIndex of marketIndexes) {
1349
1491
  if (!marketIndex.eq(new BN(100))) {
1350
- const market = this.getMarketAccount(marketIndex);
1492
+ const market = this.getPerpMarketAccount(marketIndex);
1351
1493
  marketAccountInfos.push({
1352
1494
  pubkey: market.pubkey,
1353
1495
  isWritable: true,
@@ -1371,6 +1513,54 @@ export class ClearingHouse {
1371
1513
  });
1372
1514
  }
1373
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
+
1374
1564
  public async cancelOrder(orderId?: BN): Promise<TransactionSignature> {
1375
1565
  const { txSig } = await this.txSender.send(
1376
1566
  wrapInTx(await this.getCancelOrderIx(orderId)),
@@ -1412,7 +1602,7 @@ export class ClearingHouse {
1412
1602
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1413
1603
 
1414
1604
  const order = this.getOrderByUserId(userOrderId);
1415
- const oracle = this.getMarketAccount(order.marketIndex).amm.oracle;
1605
+ const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
1416
1606
 
1417
1607
  const remainingAccounts = this.getRemainingAccounts({});
1418
1608
 
@@ -1453,7 +1643,7 @@ export class ClearingHouse {
1453
1643
  public async getFillOrderIx(
1454
1644
  userAccountPublicKey: PublicKey,
1455
1645
  userAccount: UserAccount,
1456
- order: Order,
1646
+ order: Pick<Order, 'marketIndex' | 'orderId'>,
1457
1647
  makerInfo?: MakerInfo,
1458
1648
  referrerInfo?: ReferrerInfo
1459
1649
  ): Promise<TransactionInstruction> {
@@ -1470,24 +1660,26 @@ export class ClearingHouse {
1470
1660
  : userAccount.orders.find((order) =>
1471
1661
  order.orderId.eq(userAccount.nextOrderId.sub(ONE))
1472
1662
  ).marketIndex;
1473
- const marketAccount = this.getMarketAccount(marketIndex);
1663
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
1474
1664
 
1475
1665
  const oracleAccountMap = new Map<string, AccountMeta>();
1476
- const bankAccountMap = new Map<number, AccountMeta>();
1477
- const marketAccountMap = new Map<number, AccountMeta>();
1666
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
1667
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
1478
1668
 
1479
- for (const bankBalance of userAccount.bankBalances) {
1480
- if (!bankBalance.balance.eq(ZERO)) {
1481
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1482
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1483
- 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,
1484
1676
  isSigner: false,
1485
1677
  isWritable: false,
1486
1678
  });
1487
1679
 
1488
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1489
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1490
- pubkey: bankAccount.oracle,
1680
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
1681
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1682
+ pubkey: spotMarketAccount.oracle,
1491
1683
  isSigner: false,
1492
1684
  isWritable: false,
1493
1685
  });
@@ -1495,13 +1687,13 @@ export class ClearingHouse {
1495
1687
  }
1496
1688
  }
1497
1689
 
1498
- for (const position of userAccount.positions) {
1690
+ for (const position of userAccount.perpPositions) {
1499
1691
  if (
1500
1692
  !positionIsAvailable(position) &&
1501
1693
  !position.marketIndex.eq(order.marketIndex)
1502
1694
  ) {
1503
- const market = this.getMarketAccount(position.marketIndex);
1504
- marketAccountMap.set(position.marketIndex.toNumber(), {
1695
+ const market = this.getPerpMarketAccount(position.marketIndex);
1696
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
1505
1697
  pubkey: market.pubkey,
1506
1698
  isWritable: false,
1507
1699
  isSigner: false,
@@ -1514,7 +1706,7 @@ export class ClearingHouse {
1514
1706
  }
1515
1707
  }
1516
1708
 
1517
- marketAccountMap.set(marketIndex.toNumber(), {
1709
+ perpMarketAccountMap.set(marketIndex.toNumber(), {
1518
1710
  pubkey: marketAccount.pubkey,
1519
1711
  isWritable: true,
1520
1712
  isSigner: false,
@@ -1527,8 +1719,8 @@ export class ClearingHouse {
1527
1719
 
1528
1720
  const remainingAccounts = [
1529
1721
  ...oracleAccountMap.values(),
1530
- ...bankAccountMap.values(),
1531
- ...marketAccountMap.values(),
1722
+ ...spotMarketAccountMap.values(),
1723
+ ...perpMarketAccountMap.values(),
1532
1724
  ];
1533
1725
 
1534
1726
  if (makerInfo) {
@@ -1573,45 +1765,101 @@ export class ClearingHouse {
1573
1765
  });
1574
1766
  }
1575
1767
 
1576
- 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(
1577
1801
  userAccountPublicKey: PublicKey,
1578
1802
  user: UserAccount,
1579
- order: Order
1803
+ order?: Order,
1804
+ fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
1805
+ makerInfo?: MakerInfo,
1806
+ referrerInfo?: ReferrerInfo
1580
1807
  ): Promise<TransactionSignature> {
1581
1808
  const { txSig } = await this.txSender.send(
1582
- 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
+ ),
1583
1819
  [],
1584
1820
  this.opts
1585
1821
  );
1586
1822
  return txSig;
1587
1823
  }
1588
1824
 
1589
- public async getTriggerOrderIx(
1825
+ public async getFillSpotOrderIx(
1590
1826
  userAccountPublicKey: PublicKey,
1591
1827
  userAccount: UserAccount,
1592
- order: Order
1828
+ order?: Order,
1829
+ fulfillmentConfig?: SerumV3FulfillmentConfigAccount,
1830
+ makerInfo?: MakerInfo,
1831
+ referrerInfo?: ReferrerInfo
1593
1832
  ): Promise<TransactionInstruction> {
1833
+ const userStatsPublicKey = getUserStatsAccountPublicKey(
1834
+ this.program.programId,
1835
+ userAccount.authority
1836
+ );
1837
+
1594
1838
  const fillerPublicKey = await this.getUserAccountPublicKey();
1839
+ const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1595
1840
 
1596
- const marketIndex = order.marketIndex;
1597
- 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;
1598
1846
 
1599
1847
  const oracleAccountMap = new Map<string, AccountMeta>();
1600
- const bankAccountMap = new Map<number, AccountMeta>();
1601
- const marketAccountMap = new Map<number, AccountMeta>();
1602
-
1603
- for (const bankBalance of userAccount.bankBalances) {
1604
- if (!bankBalance.balance.eq(ZERO)) {
1605
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1606
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1607
- 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,
1608
1856
  isSigner: false,
1609
1857
  isWritable: false,
1610
1858
  });
1611
1859
 
1612
- if (!bankAccount.oracle.equals(PublicKey.default)) {
1613
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1614
- pubkey: bankAccount.oracle,
1860
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
1861
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
1862
+ pubkey: spotMarket.oracle,
1615
1863
  isSigner: false,
1616
1864
  isWritable: false,
1617
1865
  });
@@ -1619,13 +1867,13 @@ export class ClearingHouse {
1619
1867
  }
1620
1868
  }
1621
1869
 
1622
- for (const position of userAccount.positions) {
1870
+ for (const position of userAccount.perpPositions) {
1623
1871
  if (
1624
1872
  !positionIsAvailable(position) &&
1625
1873
  !position.marketIndex.eq(order.marketIndex)
1626
1874
  ) {
1627
- const market = this.getMarketAccount(position.marketIndex);
1628
- marketAccountMap.set(position.marketIndex.toNumber(), {
1875
+ const market = this.getPerpMarketAccount(position.marketIndex);
1876
+ perpMarketAccountMap.set(position.marketIndex.toNumber(), {
1629
1877
  pubkey: market.pubkey,
1630
1878
  isWritable: false,
1631
1879
  isSigner: false,
@@ -1638,77 +1886,42 @@ export class ClearingHouse {
1638
1886
  }
1639
1887
  }
1640
1888
 
1641
- marketAccountMap.set(marketIndex.toNumber(), {
1642
- pubkey: marketAccount.pubkey,
1889
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1890
+ spotMarketAccountMap.set(marketIndex.toNumber(), {
1891
+ pubkey: spotMarketAccount.pubkey,
1643
1892
  isWritable: true,
1644
1893
  isSigner: false,
1645
1894
  });
1646
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1647
- pubkey: marketAccount.amm.oracle,
1648
- 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,
1649
1906
  isSigner: false,
1650
1907
  });
1651
1908
 
1652
1909
  const remainingAccounts = [
1653
1910
  ...oracleAccountMap.values(),
1654
- ...bankAccountMap.values(),
1655
- ...marketAccountMap.values(),
1911
+ ...spotMarketAccountMap.values(),
1912
+ ...perpMarketAccountMap.values(),
1656
1913
  ];
1657
1914
 
1658
- const orderId = order.orderId;
1659
- return await this.program.instruction.triggerOrder(orderId, {
1660
- accounts: {
1661
- state: await this.getStatePublicKey(),
1662
- filler: fillerPublicKey,
1663
- user: userAccountPublicKey,
1664
- authority: this.wallet.publicKey,
1665
- },
1666
- remainingAccounts,
1667
- });
1668
- }
1669
-
1670
- public async placeAndTake(
1671
- orderParams: OptionalOrderParams,
1672
- makerInfo?: MakerInfo,
1673
- referrerInfo?: ReferrerInfo
1674
- ): Promise<TransactionSignature> {
1675
- const { txSig, slot } = await this.txSender.send(
1676
- wrapInTx(
1677
- await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
1678
- ),
1679
- [],
1680
- this.opts
1681
- );
1682
- this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1683
- return txSig;
1684
- }
1685
-
1686
- public async getPlaceAndTakeIx(
1687
- orderParams: OptionalOrderParams,
1688
- makerInfo?: MakerInfo,
1689
- referrerInfo?: ReferrerInfo
1690
- ): Promise<TransactionInstruction> {
1691
- orderParams = this.getOrderParams(orderParams);
1692
- const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
1693
- const userAccountPublicKey = await this.getUserAccountPublicKey();
1694
-
1695
- const remainingAccounts = this.getRemainingAccounts({
1696
- writableMarketIndex: orderParams.marketIndex,
1697
- writableBankIndex: QUOTE_ASSET_BANK_INDEX,
1698
- });
1699
-
1700
- let makerOrderId = null;
1701
1915
  if (makerInfo) {
1702
- makerOrderId = makerInfo.order.orderId;
1703
1916
  remainingAccounts.push({
1704
1917
  pubkey: makerInfo.maker,
1705
- isSigner: false,
1706
1918
  isWritable: true,
1919
+ isSigner: false,
1707
1920
  });
1708
1921
  remainingAccounts.push({
1709
1922
  pubkey: makerInfo.makerStats,
1710
- isSigner: false,
1711
1923
  isWritable: true,
1924
+ isSigner: false,
1712
1925
  });
1713
1926
  }
1714
1927
 
@@ -1725,20 +1938,381 @@ export class ClearingHouse {
1725
1938
  });
1726
1939
  }
1727
1940
 
1728
- return await this.program.instruction.placeAndTake(
1729
- orderParams,
1730
- makerOrderId,
1731
- {
1732
- accounts: {
1733
- state: await this.getStatePublicKey(),
1734
- user: userAccountPublicKey,
1735
- userStats: userStatsPublicKey,
1736
- authority: this.wallet.publicKey,
1737
- },
1738
- remainingAccounts,
1739
- }
1740
- );
1741
- }
1941
+ const orderId = order.orderId;
1942
+ const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1943
+
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
+ }
1742
2316
 
1743
2317
  public async placeAndMake(
1744
2318
  orderParams: OptionalOrderParams,
@@ -1763,14 +2337,14 @@ export class ClearingHouse {
1763
2337
  takerInfo: TakerInfo,
1764
2338
  referrerInfo?: ReferrerInfo
1765
2339
  ): Promise<TransactionInstruction> {
1766
- orderParams = this.getOrderParams(orderParams);
2340
+ orderParams = this.getOrderParams(orderParams, MarketType.PERP);
1767
2341
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1768
2342
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1769
2343
 
1770
2344
  // todo merge this with getRemainingAccounts
1771
2345
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1772
2346
  counterPartyUserAccount: takerInfo.takerUserAccount,
1773
- writableMarketIndex: orderParams.marketIndex,
2347
+ writablePerpMarketIndex: orderParams.marketIndex,
1774
2348
  });
1775
2349
 
1776
2350
  if (referrerInfo) {
@@ -1883,13 +2457,110 @@ export class ClearingHouse {
1883
2457
  settleeUserAccount: UserAccount,
1884
2458
  marketIndex: BN
1885
2459
  ): Promise<TransactionInstruction> {
1886
- const marketAccountMap = new Map<number, AccountMeta>();
2460
+ const perpMarketAccountMap = new Map<number, AccountMeta>();
1887
2461
  const oracleAccountMap = new Map<string, AccountMeta>();
1888
- const bankAccountMap = new Map<number, AccountMeta>();
2462
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
1889
2463
 
1890
- for (const position of settleeUserAccount.positions) {
2464
+ for (const position of settleeUserAccount.perpPositions) {
1891
2465
  if (!positionIsAvailable(position)) {
1892
- const market = this.getMarketAccount(position.marketIndex);
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
+ }
2499
+
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) {
2562
+ if (!positionIsAvailable(position)) {
2563
+ const market = this.getPerpMarketAccount(position.marketIndex);
1893
2564
  marketAccountMap.set(position.marketIndex.toNumber(), {
1894
2565
  pubkey: market.pubkey,
1895
2566
  isWritable: false,
@@ -1903,15 +2574,17 @@ export class ClearingHouse {
1903
2574
  }
1904
2575
  }
1905
2576
 
1906
- for (const userBankBalance of settleeUserAccount.bankBalances) {
1907
- if (!userBankBalance.balance.eq(QUOTE_ASSET_BANK_INDEX)) {
1908
- const bankAccount = this.getBankAccount(userBankBalance.bankIndex);
1909
- 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(), {
1910
2583
  pubkey: bankAccount.pubkey,
1911
2584
  isSigner: false,
1912
2585
  isWritable: false,
1913
2586
  });
1914
- if (!bankAccount.bankIndex.eq(ZERO)) {
2587
+ if (!bankAccount.marketIndex.eq(ZERO)) {
1915
2588
  oracleAccountMap.set(bankAccount.oracle.toString(), {
1916
2589
  pubkey: bankAccount.oracle,
1917
2590
  isSigner: false,
@@ -1921,7 +2594,7 @@ export class ClearingHouse {
1921
2594
  }
1922
2595
  }
1923
2596
 
1924
- const marketAccount = this.getMarketAccount(marketIndex.toNumber());
2597
+ const marketAccount = this.getPerpMarketAccount(marketIndex.toNumber());
1925
2598
  marketAccountMap.set(marketIndex.toNumber(), {
1926
2599
  pubkey: marketAccount.pubkey,
1927
2600
  isSigner: false,
@@ -1933,19 +2606,19 @@ export class ClearingHouse {
1933
2606
  isWritable: false,
1934
2607
  });
1935
2608
 
1936
- bankAccountMap.set(QUOTE_ASSET_BANK_INDEX.toNumber(), {
1937
- 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,
1938
2611
  isSigner: false,
1939
2612
  isWritable: true,
1940
2613
  });
1941
2614
 
1942
2615
  const remainingAccounts = [
1943
2616
  ...oracleAccountMap.values(),
1944
- ...bankAccountMap.values(),
2617
+ ...spotMarketAccountMap.values(),
1945
2618
  ...marketAccountMap.values(),
1946
2619
  ];
1947
2620
 
1948
- return await this.program.instruction.settlePnl(marketIndex, {
2621
+ return await this.program.instruction.settleExpiredPosition(marketIndex, {
1949
2622
  accounts: {
1950
2623
  state: await this.getStatePublicKey(),
1951
2624
  authority: this.wallet.publicKey,
@@ -1961,7 +2634,7 @@ export class ClearingHouse {
1961
2634
  marketIndex: BN,
1962
2635
  maxBaseAssetAmount: BN
1963
2636
  ): Promise<TransactionSignature> {
1964
- const { txSig } = await this.txSender.send(
2637
+ const { txSig, slot } = await this.txSender.send(
1965
2638
  wrapInTx(
1966
2639
  await this.getLiquidatePerpIx(
1967
2640
  userAccountPublicKey,
@@ -1973,6 +2646,7 @@ export class ClearingHouse {
1973
2646
  [],
1974
2647
  this.opts
1975
2648
  );
2649
+ this.marketLastSlotCache.set(marketIndex.toNumber(), slot);
1976
2650
  return txSig;
1977
2651
  }
1978
2652
 
@@ -1991,7 +2665,7 @@ export class ClearingHouse {
1991
2665
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
1992
2666
 
1993
2667
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1994
- writableMarketIndex: marketIndex,
2668
+ writablePerpMarketIndex: marketIndex,
1995
2669
  counterPartyUserAccount: userAccount,
1996
2670
  });
1997
2671
 
@@ -2015,8 +2689,8 @@ export class ClearingHouse {
2015
2689
  public async liquidateBorrow(
2016
2690
  userAccountPublicKey: PublicKey,
2017
2691
  userAccount: UserAccount,
2018
- assetBankIndex: BN,
2019
- liabilityBankIndex: BN,
2692
+ assetmarketIndex: BN,
2693
+ liabilitymarketIndex: BN,
2020
2694
  maxLiabilityTransfer: BN
2021
2695
  ): Promise<TransactionSignature> {
2022
2696
  const { txSig } = await this.txSender.send(
@@ -2024,8 +2698,8 @@ export class ClearingHouse {
2024
2698
  await this.getLiquidateBorrowIx(
2025
2699
  userAccountPublicKey,
2026
2700
  userAccount,
2027
- assetBankIndex,
2028
- liabilityBankIndex,
2701
+ assetmarketIndex,
2702
+ liabilitymarketIndex,
2029
2703
  maxLiabilityTransfer
2030
2704
  )
2031
2705
  ),
@@ -2038,20 +2712,20 @@ export class ClearingHouse {
2038
2712
  public async getLiquidateBorrowIx(
2039
2713
  userAccountPublicKey: PublicKey,
2040
2714
  userAccount: UserAccount,
2041
- assetBankIndex: BN,
2042
- liabilityBankIndex: BN,
2715
+ assetmarketIndex: BN,
2716
+ liabilitymarketIndex: BN,
2043
2717
  maxLiabilityTransfer: BN
2044
2718
  ): Promise<TransactionInstruction> {
2045
2719
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2046
2720
 
2047
2721
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2048
2722
  counterPartyUserAccount: userAccount,
2049
- writableBankIndexes: [liabilityBankIndex, assetBankIndex],
2723
+ writableSpotMarketIndexes: [liabilitymarketIndex, assetmarketIndex],
2050
2724
  });
2051
2725
 
2052
2726
  return await this.program.instruction.liquidateBorrow(
2053
- assetBankIndex,
2054
- liabilityBankIndex,
2727
+ assetmarketIndex,
2728
+ liabilitymarketIndex,
2055
2729
  maxLiabilityTransfer,
2056
2730
  {
2057
2731
  accounts: {
@@ -2069,22 +2743,23 @@ export class ClearingHouse {
2069
2743
  userAccountPublicKey: PublicKey,
2070
2744
  userAccount: UserAccount,
2071
2745
  perpMarketIndex: BN,
2072
- liabilityBankIndex: BN,
2746
+ liabilitymarketIndex: BN,
2073
2747
  maxLiabilityTransfer: BN
2074
2748
  ): Promise<TransactionSignature> {
2075
- const { txSig } = await this.txSender.send(
2749
+ const { txSig, slot } = await this.txSender.send(
2076
2750
  wrapInTx(
2077
2751
  await this.getLiquidateBorrowForPerpPnlIx(
2078
2752
  userAccountPublicKey,
2079
2753
  userAccount,
2080
2754
  perpMarketIndex,
2081
- liabilityBankIndex,
2755
+ liabilitymarketIndex,
2082
2756
  maxLiabilityTransfer
2083
2757
  )
2084
2758
  ),
2085
2759
  [],
2086
2760
  this.opts
2087
2761
  );
2762
+ this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
2088
2763
  return txSig;
2089
2764
  }
2090
2765
 
@@ -2092,20 +2767,20 @@ export class ClearingHouse {
2092
2767
  userAccountPublicKey: PublicKey,
2093
2768
  userAccount: UserAccount,
2094
2769
  perpMarketIndex: BN,
2095
- liabilityBankIndex: BN,
2770
+ liabilitymarketIndex: BN,
2096
2771
  maxLiabilityTransfer: BN
2097
2772
  ): Promise<TransactionInstruction> {
2098
2773
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2099
2774
 
2100
2775
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2101
2776
  counterPartyUserAccount: userAccount,
2102
- writableMarketIndex: perpMarketIndex,
2103
- writableBankIndexes: [liabilityBankIndex],
2777
+ writablePerpMarketIndex: perpMarketIndex,
2778
+ writableSpotMarketIndexes: [liabilitymarketIndex],
2104
2779
  });
2105
2780
 
2106
2781
  return await this.program.instruction.liquidateBorrowForPerpPnl(
2107
2782
  perpMarketIndex,
2108
- liabilityBankIndex,
2783
+ liabilitymarketIndex,
2109
2784
  maxLiabilityTransfer,
2110
2785
  {
2111
2786
  accounts: {
@@ -2123,22 +2798,23 @@ export class ClearingHouse {
2123
2798
  userAccountPublicKey: PublicKey,
2124
2799
  userAccount: UserAccount,
2125
2800
  perpMarketIndex: BN,
2126
- assetBankIndex: BN,
2801
+ assetMarketIndex: BN,
2127
2802
  maxPnlTransfer: BN
2128
2803
  ): Promise<TransactionSignature> {
2129
- const { txSig } = await this.txSender.send(
2804
+ const { txSig, slot } = await this.txSender.send(
2130
2805
  wrapInTx(
2131
2806
  await this.getLiquidatePerpPnlForDepositIx(
2132
2807
  userAccountPublicKey,
2133
2808
  userAccount,
2134
2809
  perpMarketIndex,
2135
- assetBankIndex,
2810
+ assetMarketIndex,
2136
2811
  maxPnlTransfer
2137
2812
  )
2138
2813
  ),
2139
2814
  [],
2140
2815
  this.opts
2141
2816
  );
2817
+ this.marketLastSlotCache.set(perpMarketIndex.toNumber(), slot);
2142
2818
  return txSig;
2143
2819
  }
2144
2820
 
@@ -2146,20 +2822,20 @@ export class ClearingHouse {
2146
2822
  userAccountPublicKey: PublicKey,
2147
2823
  userAccount: UserAccount,
2148
2824
  perpMarketIndex: BN,
2149
- assetBankIndex: BN,
2825
+ assetMarketIndex: BN,
2150
2826
  maxPnlTransfer: BN
2151
2827
  ): Promise<TransactionInstruction> {
2152
2828
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2153
2829
 
2154
2830
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2155
2831
  counterPartyUserAccount: userAccount,
2156
- writableMarketIndex: perpMarketIndex,
2157
- writableBankIndexes: [assetBankIndex],
2832
+ writablePerpMarketIndex: perpMarketIndex,
2833
+ writableSpotMarketIndexes: [assetMarketIndex],
2158
2834
  });
2159
2835
 
2160
2836
  return await this.program.instruction.liquidatePerpPnlForDeposit(
2161
2837
  perpMarketIndex,
2162
- assetBankIndex,
2838
+ assetMarketIndex,
2163
2839
  maxPnlTransfer,
2164
2840
  {
2165
2841
  accounts: {
@@ -2176,7 +2852,6 @@ export class ClearingHouse {
2176
2852
  public async resolvePerpBankruptcy(
2177
2853
  userAccountPublicKey: PublicKey,
2178
2854
  userAccount: UserAccount,
2179
- bankIndex: BN,
2180
2855
  marketIndex: BN
2181
2856
  ): Promise<TransactionSignature> {
2182
2857
  const { txSig } = await this.txSender.send(
@@ -2184,7 +2859,6 @@ export class ClearingHouse {
2184
2859
  await this.getResolvePerpBankruptcyIx(
2185
2860
  userAccountPublicKey,
2186
2861
  userAccount,
2187
- bankIndex,
2188
2862
  marketIndex
2189
2863
  )
2190
2864
  ),
@@ -2197,21 +2871,20 @@ export class ClearingHouse {
2197
2871
  public async getResolvePerpBankruptcyIx(
2198
2872
  userAccountPublicKey: PublicKey,
2199
2873
  userAccount: UserAccount,
2200
- bankIndex: BN,
2201
2874
  marketIndex: BN
2202
2875
  ): Promise<TransactionInstruction> {
2203
2876
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2204
2877
 
2205
2878
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2206
- writableMarketIndex: marketIndex,
2207
- writableBankIndexes: [bankIndex],
2879
+ writablePerpMarketIndex: marketIndex,
2880
+ writableSpotMarketIndexes: [QUOTE_SPOT_MARKET_INDEX],
2208
2881
  counterPartyUserAccount: userAccount,
2209
2882
  });
2210
2883
 
2211
- const bank = this.getBankAccount(bankIndex);
2884
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2212
2885
 
2213
2886
  return await this.program.instruction.resolvePerpBankruptcy(
2214
- bankIndex,
2887
+ QUOTE_SPOT_MARKET_INDEX,
2215
2888
  marketIndex,
2216
2889
  {
2217
2890
  accounts: {
@@ -2219,9 +2892,9 @@ export class ClearingHouse {
2219
2892
  authority: this.wallet.publicKey,
2220
2893
  user: userAccountPublicKey,
2221
2894
  liquidator: liquidatorPublicKey,
2222
- bankVault: bank.vault,
2223
- insuranceFundVault: bank.insuranceFundVault,
2224
- insuranceFundVaultAuthority: bank.insuranceFundVaultAuthority,
2895
+ spotMarketVault: spotMarket.vault,
2896
+ insuranceFundVault: spotMarket.insuranceFundVault,
2897
+ clearingHouseSigner: this.getSignerPublicKey(),
2225
2898
  tokenProgram: TOKEN_PROGRAM_ID,
2226
2899
  },
2227
2900
  remainingAccounts: remainingAccounts,
@@ -2232,14 +2905,14 @@ export class ClearingHouse {
2232
2905
  public async resolveBorrowBankruptcy(
2233
2906
  userAccountPublicKey: PublicKey,
2234
2907
  userAccount: UserAccount,
2235
- bankIndex: BN
2908
+ marketIndex: BN
2236
2909
  ): Promise<TransactionSignature> {
2237
2910
  const { txSig } = await this.txSender.send(
2238
2911
  wrapInTx(
2239
2912
  await this.getResolveBorrowBankruptcyIx(
2240
2913
  userAccountPublicKey,
2241
2914
  userAccount,
2242
- bankIndex
2915
+ marketIndex
2243
2916
  )
2244
2917
  ),
2245
2918
  [],
@@ -2251,26 +2924,26 @@ export class ClearingHouse {
2251
2924
  public async getResolveBorrowBankruptcyIx(
2252
2925
  userAccountPublicKey: PublicKey,
2253
2926
  userAccount: UserAccount,
2254
- bankIndex: BN
2927
+ marketIndex: BN
2255
2928
  ): Promise<TransactionInstruction> {
2256
2929
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2257
2930
 
2258
2931
  const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2259
- writableBankIndexes: [bankIndex],
2932
+ writableSpotMarketIndexes: [marketIndex],
2260
2933
  counterPartyUserAccount: userAccount,
2261
2934
  });
2262
2935
 
2263
- const bank = this.getBankAccount(bankIndex);
2936
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2264
2937
 
2265
- return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
2938
+ return await this.program.instruction.resolveBorrowBankruptcy(marketIndex, {
2266
2939
  accounts: {
2267
2940
  state: await this.getStatePublicKey(),
2268
2941
  authority: this.wallet.publicKey,
2269
2942
  user: userAccountPublicKey,
2270
2943
  liquidator: liquidatorPublicKey,
2271
- bankVault: bank.vault,
2272
- insuranceFundVault: bank.insuranceFundVault,
2273
- insuranceFundVaultAuthority: bank.insuranceFundVaultAuthority,
2944
+ spotMarketVault: spotMarket.vault,
2945
+ insuranceFundVault: spotMarket.insuranceFundVault,
2946
+ clearingHouseSigner: this.getSignerPublicKey(),
2274
2947
  tokenProgram: TOKEN_PROGRAM_ID,
2275
2948
  },
2276
2949
  remainingAccounts: remainingAccounts,
@@ -2279,35 +2952,35 @@ export class ClearingHouse {
2279
2952
 
2280
2953
  getRemainingAccountsWithCounterparty(params: {
2281
2954
  counterPartyUserAccount: UserAccount;
2282
- writableMarketIndex?: BN;
2283
- writableBankIndexes?: BN[];
2955
+ writablePerpMarketIndex?: BN;
2956
+ writableSpotMarketIndexes?: BN[];
2284
2957
  }): AccountMeta[] {
2285
2958
  const counterPartyUserAccount = params.counterPartyUserAccount;
2286
2959
 
2287
2960
  const oracleAccountMap = new Map<string, AccountMeta>();
2288
- const bankAccountMap = new Map<number, AccountMeta>();
2961
+ const spotMarketAccountMap = new Map<number, AccountMeta>();
2289
2962
  const marketAccountMap = new Map<number, AccountMeta>();
2290
- for (const bankBalance of counterPartyUserAccount.bankBalances) {
2291
- if (!bankBalance.balance.eq(ZERO)) {
2292
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
2293
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
2294
- 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,
2295
2968
  isSigner: false,
2296
2969
  isWritable: false,
2297
2970
  });
2298
2971
 
2299
- if (!bankAccount.oracle.equals(PublicKey.default)) {
2300
- oracleAccountMap.set(bankAccount.oracle.toString(), {
2301
- pubkey: bankAccount.oracle,
2972
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
2973
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
2974
+ pubkey: spotMarket.oracle,
2302
2975
  isSigner: false,
2303
2976
  isWritable: false,
2304
2977
  });
2305
2978
  }
2306
2979
  }
2307
2980
  }
2308
- for (const position of counterPartyUserAccount.positions) {
2981
+ for (const position of counterPartyUserAccount.perpPositions) {
2309
2982
  if (!positionIsAvailable(position)) {
2310
- const market = this.getMarketAccount(position.marketIndex);
2983
+ const market = this.getPerpMarketAccount(position.marketIndex);
2311
2984
  marketAccountMap.set(position.marketIndex.toNumber(), {
2312
2985
  pubkey: market.pubkey,
2313
2986
  isWritable: false,
@@ -2334,7 +3007,7 @@ export class ClearingHouse {
2334
3007
  // if cache has more recent slot than user positions account slot, add market to remaining accounts
2335
3008
  // otherwise remove from slot
2336
3009
  if (slot > lastUserPositionsSlot) {
2337
- const marketAccount = this.getMarketAccount(marketIndexNum);
3010
+ const marketAccount = this.getPerpMarketAccount(marketIndexNum);
2338
3011
  marketAccountMap.set(marketIndexNum, {
2339
3012
  pubkey: marketAccount.pubkey,
2340
3013
  isSigner: false,
@@ -2349,27 +3022,27 @@ export class ClearingHouse {
2349
3022
  this.marketLastSlotCache.delete(marketIndexNum);
2350
3023
  }
2351
3024
  }
2352
- for (const bankBalance of userAccount.bankBalances) {
2353
- if (!bankBalance.balance.eq(ZERO)) {
2354
- const bankAccount = this.getBankAccount(bankBalance.bankIndex);
2355
- bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
2356
- 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,
2357
3030
  isSigner: false,
2358
3031
  isWritable: false,
2359
3032
  });
2360
3033
 
2361
- if (!bankAccount.oracle.equals(PublicKey.default)) {
2362
- oracleAccountMap.set(bankAccount.oracle.toString(), {
2363
- pubkey: bankAccount.oracle,
3034
+ if (!spotMarket.oracle.equals(PublicKey.default)) {
3035
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
3036
+ pubkey: spotMarket.oracle,
2364
3037
  isSigner: false,
2365
3038
  isWritable: false,
2366
3039
  });
2367
3040
  }
2368
3041
  }
2369
3042
  }
2370
- for (const position of userAccount.positions) {
3043
+ for (const position of userAccount.perpPositions) {
2371
3044
  if (!positionIsAvailable(position)) {
2372
- const market = this.getMarketAccount(position.marketIndex);
3045
+ const market = this.getPerpMarketAccount(position.marketIndex);
2373
3046
  marketAccountMap.set(position.marketIndex.toNumber(), {
2374
3047
  pubkey: market.pubkey,
2375
3048
  isWritable: false,
@@ -2383,8 +3056,8 @@ export class ClearingHouse {
2383
3056
  }
2384
3057
  }
2385
3058
 
2386
- if (params.writableMarketIndex) {
2387
- const market = this.getMarketAccount(params.writableMarketIndex);
3059
+ if (params.writablePerpMarketIndex) {
3060
+ const market = this.getPerpMarketAccount(params.writablePerpMarketIndex);
2388
3061
  marketAccountMap.set(market.marketIndex.toNumber(), {
2389
3062
  pubkey: market.pubkey,
2390
3063
  isSigner: false,
@@ -2397,17 +3070,19 @@ export class ClearingHouse {
2397
3070
  });
2398
3071
  }
2399
3072
 
2400
- if (params.writableBankIndexes) {
2401
- for (const writableBankIndex of params.writableBankIndexes) {
2402
- const bank = this.getBankAccount(writableBankIndex);
2403
- bankAccountMap.set(bank.bankIndex.toNumber(), {
2404
- 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,
2405
3080
  isSigner: false,
2406
3081
  isWritable: true,
2407
3082
  });
2408
- if (!bank.oracle.equals(PublicKey.default)) {
2409
- oracleAccountMap.set(bank.oracle.toString(), {
2410
- pubkey: bank.oracle,
3083
+ if (!spotMarketAccount.oracle.equals(PublicKey.default)) {
3084
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
3085
+ pubkey: spotMarketAccount.oracle,
2411
3086
  isSigner: false,
2412
3087
  isWritable: false,
2413
3088
  });
@@ -2417,7 +3092,7 @@ export class ClearingHouse {
2417
3092
 
2418
3093
  return [
2419
3094
  ...oracleAccountMap.values(),
2420
- ...bankAccountMap.values(),
3095
+ ...spotMarketAccountMap.values(),
2421
3096
  ...marketAccountMap.values(),
2422
3097
  ];
2423
3098
  }
@@ -2465,7 +3140,7 @@ export class ClearingHouse {
2465
3140
  userAccount
2466
3141
  )) as UserAccount;
2467
3142
 
2468
- const userPositions = user.positions;
3143
+ const userPositions = user.perpPositions;
2469
3144
 
2470
3145
  const remainingAccounts = [];
2471
3146
  for (const position of userPositions) {
@@ -2496,17 +3171,17 @@ export class ClearingHouse {
2496
3171
  }
2497
3172
 
2498
3173
  public getOracleDataForMarket(marketIndex: BN): OraclePriceData {
2499
- const oracleKey = this.getMarketAccount(marketIndex).amm.oracle;
3174
+ const oracleKey = this.getPerpMarketAccount(marketIndex).amm.oracle;
2500
3175
  const oracleData = this.getOraclePriceDataAndSlot(oracleKey).data;
2501
3176
 
2502
3177
  return oracleData;
2503
3178
  }
2504
3179
 
2505
3180
  public async initializeInsuranceFundStake(
2506
- bankIndex: BN
3181
+ marketIndex: BN
2507
3182
  ): Promise<TransactionSignature> {
2508
3183
  const { txSig } = await this.txSender.send(
2509
- wrapInTx(await this.getInitializeInsuranceFundStakeIx(bankIndex)),
3184
+ wrapInTx(await this.getInitializeInsuranceFundStakeIx(marketIndex)),
2510
3185
  [],
2511
3186
  this.opts
2512
3187
  );
@@ -2514,20 +3189,20 @@ export class ClearingHouse {
2514
3189
  }
2515
3190
 
2516
3191
  public async getInitializeInsuranceFundStakeIx(
2517
- bankIndex: BN
3192
+ marketIndex: BN
2518
3193
  ): Promise<TransactionInstruction> {
2519
3194
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2520
3195
  this.program.programId,
2521
3196
  this.wallet.publicKey,
2522
- bankIndex
3197
+ marketIndex
2523
3198
  );
2524
3199
 
2525
3200
  return await this.program.instruction.initializeInsuranceFundStake(
2526
- bankIndex,
3201
+ marketIndex,
2527
3202
  {
2528
3203
  accounts: {
2529
3204
  insuranceFundStake: ifStakeAccountPublicKey,
2530
- bank: this.getBankAccount(bankIndex).pubkey,
3205
+ spotMarket: this.getSpotMarketAccount(marketIndex).pubkey,
2531
3206
  userStats: this.getUserStatsAccountPublicKey(),
2532
3207
  authority: this.wallet.publicKey,
2533
3208
  payer: this.wallet.publicKey,
@@ -2540,29 +3215,29 @@ export class ClearingHouse {
2540
3215
  }
2541
3216
 
2542
3217
  public async addInsuranceFundStake(
2543
- bankIndex: BN,
3218
+ marketIndex: BN,
2544
3219
  amount: BN,
2545
3220
  collateralAccountPublicKey: PublicKey
2546
3221
  ): Promise<TransactionSignature> {
2547
- const bank = this.getBankAccount(bankIndex);
3222
+ const spotMarket = this.getSpotMarketAccount(marketIndex);
2548
3223
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2549
3224
  this.program.programId,
2550
3225
  this.wallet.publicKey,
2551
- bankIndex
3226
+ marketIndex
2552
3227
  );
2553
3228
 
2554
3229
  const remainingAccounts = this.getRemainingAccounts({
2555
- writableBankIndex: bankIndex,
3230
+ writableSpotMarketIndex: marketIndex,
2556
3231
  });
2557
3232
 
2558
- return await this.program.rpc.addInsuranceFundStake(bankIndex, amount, {
3233
+ return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
2559
3234
  accounts: {
2560
3235
  state: await this.getStatePublicKey(),
2561
- bank: bank.pubkey,
3236
+ spotMarket: spotMarket.pubkey,
2562
3237
  insuranceFundStake: ifStakeAccountPublicKey,
2563
3238
  userStats: this.getUserStatsAccountPublicKey(),
2564
3239
  authority: this.wallet.publicKey,
2565
- insuranceFundVault: bank.insuranceFundVault,
3240
+ insuranceFundVault: spotMarket.insuranceFundVault,
2566
3241
  userTokenAccount: collateralAccountPublicKey,
2567
3242
  tokenProgram: TOKEN_PROGRAM_ID,
2568
3243
  },
@@ -2571,31 +3246,31 @@ export class ClearingHouse {
2571
3246
  }
2572
3247
 
2573
3248
  public async requestRemoveInsuranceFundStake(
2574
- bankIndex: BN,
3249
+ marketIndex: BN,
2575
3250
  amount: BN
2576
3251
  ): Promise<TransactionSignature> {
2577
- const bank = this.getBankAccount(bankIndex);
3252
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2578
3253
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2579
3254
  this.program.programId,
2580
3255
  this.wallet.publicKey,
2581
- bankIndex
3256
+ marketIndex
2582
3257
  );
2583
3258
 
2584
3259
  const remainingAccounts = this.getRemainingAccounts({
2585
- writableBankIndex: bankIndex,
3260
+ writableSpotMarketIndex: marketIndex,
2586
3261
  });
2587
3262
 
2588
3263
  return await this.program.rpc.requestRemoveInsuranceFundStake(
2589
- bankIndex,
3264
+ marketIndex,
2590
3265
  amount,
2591
3266
  {
2592
3267
  accounts: {
2593
3268
  state: await this.getStatePublicKey(),
2594
- bank: bank.pubkey,
3269
+ spotMarket: spotMarketAccount.pubkey,
2595
3270
  insuranceFundStake: ifStakeAccountPublicKey,
2596
3271
  userStats: this.getUserStatsAccountPublicKey(),
2597
3272
  authority: this.wallet.publicKey,
2598
- insuranceFundVault: bank.insuranceFundVault,
3273
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2599
3274
  // userTokenAccount: collateralAccountPublicKey,
2600
3275
  // tokenProgram: TOKEN_PROGRAM_ID,
2601
3276
  },
@@ -2605,29 +3280,29 @@ export class ClearingHouse {
2605
3280
  }
2606
3281
 
2607
3282
  public async cancelRequestRemoveInsuranceFundStake(
2608
- bankIndex: BN
3283
+ marketIndex: BN
2609
3284
  ): Promise<TransactionSignature> {
2610
- const bank = this.getBankAccount(bankIndex);
3285
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2611
3286
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2612
3287
  this.program.programId,
2613
3288
  this.wallet.publicKey,
2614
- bankIndex
3289
+ marketIndex
2615
3290
  );
2616
3291
 
2617
3292
  const remainingAccounts = this.getRemainingAccounts({
2618
- writableBankIndex: bankIndex,
3293
+ writableSpotMarketIndex: marketIndex,
2619
3294
  });
2620
3295
 
2621
3296
  return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(
2622
- bankIndex,
3297
+ marketIndex,
2623
3298
  {
2624
3299
  accounts: {
2625
3300
  state: await this.getStatePublicKey(),
2626
- bank: bank.pubkey,
3301
+ spotMarket: spotMarketAccount.pubkey,
2627
3302
  insuranceFundStake: ifStakeAccountPublicKey,
2628
3303
  userStats: this.getUserStatsAccountPublicKey(),
2629
3304
  authority: this.wallet.publicKey,
2630
- insuranceFundVault: bank.insuranceFundVault,
3305
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2631
3306
  // userTokenAccount: collateralAccountPublicKey,
2632
3307
  // tokenProgram: TOKEN_PROGRAM_ID,
2633
3308
  },
@@ -2637,29 +3312,29 @@ export class ClearingHouse {
2637
3312
  }
2638
3313
 
2639
3314
  public async removeInsuranceFundStake(
2640
- bankIndex: BN,
3315
+ marketIndex: BN,
2641
3316
  collateralAccountPublicKey: PublicKey
2642
3317
  ): Promise<TransactionSignature> {
2643
- const bank = this.getBankAccount(bankIndex);
3318
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2644
3319
  const ifStakeAccountPublicKey = getInsuranceFundStakeAccountPublicKey(
2645
3320
  this.program.programId,
2646
3321
  this.wallet.publicKey,
2647
- bankIndex
3322
+ marketIndex
2648
3323
  );
2649
3324
 
2650
3325
  const remainingAccounts = this.getRemainingAccounts({
2651
- writableBankIndex: bankIndex,
3326
+ writableSpotMarketIndex: marketIndex,
2652
3327
  });
2653
3328
 
2654
- return await this.program.rpc.removeInsuranceFundStake(bankIndex, {
3329
+ return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
2655
3330
  accounts: {
2656
3331
  state: await this.getStatePublicKey(),
2657
- bank: bank.pubkey,
3332
+ spotMarket: spotMarketAccount.pubkey,
2658
3333
  insuranceFundStake: ifStakeAccountPublicKey,
2659
3334
  userStats: this.getUserStatsAccountPublicKey(),
2660
3335
  authority: this.wallet.publicKey,
2661
- insuranceFundVault: bank.insuranceFundVault,
2662
- insuranceFundVaultAuthority: bank.insuranceFundVaultAuthority,
3336
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
3337
+ clearingHouseSigner: this.getSignerPublicKey(),
2663
3338
  userTokenAccount: collateralAccountPublicKey,
2664
3339
  tokenProgram: TOKEN_PROGRAM_ID,
2665
3340
  },
@@ -2668,24 +3343,66 @@ export class ClearingHouse {
2668
3343
  }
2669
3344
 
2670
3345
  public async settleRevenueToInsuranceFund(
2671
- bankIndex: BN
3346
+ marketIndex: BN
2672
3347
  ): Promise<TransactionSignature> {
2673
- const bank = this.getBankAccount(bankIndex);
3348
+ const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2674
3349
 
2675
3350
  const remainingAccounts = this.getRemainingAccounts({
2676
- writableBankIndex: bankIndex,
3351
+ writableSpotMarketIndex: marketIndex,
2677
3352
  });
2678
3353
 
2679
- return await this.program.rpc.settleRevenueToInsuranceFund(bankIndex, {
3354
+ return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
2680
3355
  accounts: {
2681
3356
  state: await this.getStatePublicKey(),
2682
- bank: bank.pubkey,
2683
- bankVault: bank.vault,
2684
- bankVaultAuthority: bank.vaultAuthority,
2685
- insuranceFundVault: bank.insuranceFundVault,
3357
+ spotMarket: spotMarketAccount.pubkey,
3358
+ spotMarketVault: spotMarketAccount.vault,
3359
+ clearingHouseSigner: this.getSignerPublicKey(),
3360
+ insuranceFundVault: spotMarketAccount.insuranceFundVault,
2686
3361
  tokenProgram: TOKEN_PROGRAM_ID,
2687
3362
  },
2688
3363
  remainingAccounts,
2689
3364
  });
2690
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
+ }
2691
3408
  }