@drift-labs/sdk 0.2.0-master.30 → 0.2.0-master.32

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 (60) hide show
  1. package/lib/admin.d.ts +11 -7
  2. package/lib/admin.js +50 -12
  3. package/lib/clearingHouse.d.ts +26 -23
  4. package/lib/clearingHouse.js +290 -652
  5. package/lib/clearingHouseUser.d.ts +1 -1
  6. package/lib/clearingHouseUser.js +9 -12
  7. package/lib/config.js +1 -1
  8. package/lib/constants/numericConstants.d.ts +7 -0
  9. package/lib/constants/numericConstants.js +8 -1
  10. package/lib/constants/spotMarkets.js +4 -4
  11. package/lib/dlob/DLOB.d.ts +7 -5
  12. package/lib/dlob/DLOB.js +159 -88
  13. package/lib/dlob/DLOBNode.d.ts +2 -0
  14. package/lib/dlob/DLOBNode.js +3 -0
  15. package/lib/dlob/NodeList.d.ts +2 -1
  16. package/lib/dlob/NodeList.js +10 -4
  17. package/lib/events/types.d.ts +2 -1
  18. package/lib/events/types.js +1 -0
  19. package/lib/factory/bigNum.d.ts +1 -0
  20. package/lib/factory/bigNum.js +14 -0
  21. package/lib/idl/clearing_house.json +1091 -611
  22. package/lib/math/amm.d.ts +2 -2
  23. package/lib/math/amm.js +31 -28
  24. package/lib/math/market.d.ts +1 -1
  25. package/lib/math/market.js +6 -6
  26. package/lib/math/spotBalance.js +7 -8
  27. package/lib/math/trade.js +11 -11
  28. package/lib/types.d.ts +118 -41
  29. package/lib/types.js +34 -4
  30. package/package.json +4 -2
  31. package/src/admin.ts +129 -29
  32. package/src/clearingHouse.ts +380 -787
  33. package/src/clearingHouseUser.ts +11 -14
  34. package/src/config.ts +1 -1
  35. package/src/constants/numericConstants.ts +7 -0
  36. package/src/constants/spotMarkets.ts +5 -4
  37. package/src/dlob/DLOB.ts +221 -103
  38. package/src/dlob/DLOBNode.ts +5 -0
  39. package/src/dlob/NodeList.ts +15 -5
  40. package/src/events/types.ts +3 -0
  41. package/src/factory/bigNum.ts +23 -0
  42. package/src/idl/clearing_house.json +1091 -611
  43. package/src/math/amm.ts +42 -29
  44. package/src/math/market.ts +9 -4
  45. package/src/math/spotBalance.ts +11 -8
  46. package/src/math/trade.ts +11 -11
  47. package/src/types.ts +82 -41
  48. package/tests/bn/test.ts +13 -8
  49. package/tests/dlob/helpers.ts +56 -33
  50. package/tests/dlob/test.ts +1397 -495
  51. package/src/assert/assert.js +0 -9
  52. package/src/events/eventList.js +0 -77
  53. package/src/examples/makeTradeExample.js +0 -157
  54. package/src/token/index.js +0 -38
  55. package/src/tx/types.js +0 -2
  56. package/src/tx/utils.js +0 -17
  57. package/src/util/computeUnits.js +0 -27
  58. package/src/util/getTokenAddress.js +0 -9
  59. package/src/util/promiseTimeout.js +0 -14
  60. package/src/util/tps.js +0 -27
@@ -266,6 +266,15 @@ class ClearingHouse {
266
266
  isSigner: false,
267
267
  });
268
268
  }
269
+ const state = this.getStateAccount();
270
+ if (!state.whitelistMint.equals(web3_js_1.PublicKey.default)) {
271
+ const associatedTokenPublicKey = await spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, state.whitelistMint, this.wallet.publicKey);
272
+ remainingAccounts.push({
273
+ pubkey: associatedTokenPublicKey,
274
+ isWritable: false,
275
+ isSigner: false,
276
+ });
277
+ }
269
278
  const nameBuffer = (0, userName_1.encodeName)(name);
270
279
  const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
271
280
  accounts: {
@@ -330,6 +339,21 @@ class ClearingHouse {
330
339
  ]);
331
340
  return programAccounts.map((programAccount) => programAccount.account);
332
341
  }
342
+ async deleteUser(userId = 0) {
343
+ var _a;
344
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.wallet.publicKey, userId);
345
+ const txSig = await this.program.rpc.deleteUser({
346
+ accounts: {
347
+ user: userAccountPublicKey,
348
+ userStats: this.getUserStatsAccountPublicKey(),
349
+ authority: this.wallet.publicKey,
350
+ state: await this.getStatePublicKey(),
351
+ },
352
+ });
353
+ await ((_a = this.users.get(userId)) === null || _a === void 0 ? void 0 : _a.unsubscribe());
354
+ this.users.delete(userId);
355
+ return txSig;
356
+ }
333
357
  getUser(userId) {
334
358
  userId = userId !== null && userId !== void 0 ? userId : this.activeUserId;
335
359
  if (!this.users.has(userId)) {
@@ -368,47 +392,29 @@ class ClearingHouse {
368
392
  return (0, spotBalance_1.getTokenAmount)(spotPosition.balance, spotMarket, spotPosition.balanceType);
369
393
  }
370
394
  getRemainingAccounts(params) {
371
- const userAccountAndSlot = this.getUserAccountAndSlot();
372
- if (!userAccountAndSlot) {
373
- throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
374
- }
375
- const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
376
- const oracleAccountMap = new Map();
377
- const spotMarketAccountMap = new Map();
378
- const perpMarketAccountMap = new Map();
379
- for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
380
- // if cache has more recent slot than user positions account slot, add market to remaining accounts
381
- // otherwise remove from slot
382
- if (slot > lastUserPositionsSlot) {
383
- const marketAccount = this.getPerpMarketAccount(marketIndexNum);
384
- perpMarketAccountMap.set(marketIndexNum, {
385
- pubkey: marketAccount.pubkey,
386
- isSigner: false,
387
- isWritable: false,
388
- });
389
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
390
- pubkey: marketAccount.amm.oracle,
391
- isSigner: false,
392
- isWritable: false,
393
- });
394
- }
395
- else {
396
- this.marketLastSlotCache.delete(marketIndexNum);
397
- }
398
- }
399
- for (const position of userAccount.perpPositions) {
400
- if (!(0, position_1.positionIsAvailable)(position)) {
401
- const marketAccount = this.getPerpMarketAccount(position.marketIndex);
402
- perpMarketAccountMap.set(position.marketIndex, {
403
- pubkey: marketAccount.pubkey,
404
- isSigner: false,
405
- isWritable: false,
406
- });
407
- oracleAccountMap.set(marketAccount.pubkey.toString(), {
408
- pubkey: marketAccount.amm.oracle,
409
- isSigner: false,
410
- isWritable: false,
411
- });
395
+ var _a;
396
+ const { oracleAccountMap, spotMarketAccountMap, perpMarketAccountMap } = this.getRemainingAccountMapsForUsers(params.userAccounts);
397
+ if (params.useMarketLastSlotCache) {
398
+ const lastUserPositionsSlot = (_a = this.getUserAccountAndSlot()) === null || _a === void 0 ? void 0 : _a.slot;
399
+ for (const [marketIndex, slot] of this.marketLastSlotCache.entries()) {
400
+ // if cache has more recent slot than user positions account slot, add market to remaining accounts
401
+ // otherwise remove from slot
402
+ if (slot > lastUserPositionsSlot) {
403
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
404
+ perpMarketAccountMap.set(marketIndex, {
405
+ pubkey: marketAccount.pubkey,
406
+ isSigner: false,
407
+ isWritable: false,
408
+ });
409
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
410
+ pubkey: marketAccount.amm.oracle,
411
+ isSigner: false,
412
+ isWritable: false,
413
+ });
414
+ }
415
+ else {
416
+ this.marketLastSlotCache.delete(marketIndex);
417
+ }
412
418
  }
413
419
  }
414
420
  if (params.readablePerpMarketIndex !== undefined) {
@@ -424,34 +430,19 @@ class ClearingHouse {
424
430
  isWritable: false,
425
431
  });
426
432
  }
427
- if (params.writablePerpMarketIndex !== undefined) {
428
- const marketAccount = this.getPerpMarketAccount(params.writablePerpMarketIndex);
429
- perpMarketAccountMap.set(params.writablePerpMarketIndex, {
430
- pubkey: marketAccount.pubkey,
431
- isSigner: false,
432
- isWritable: true,
433
- });
434
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
435
- pubkey: marketAccount.amm.oracle,
436
- isSigner: false,
437
- isWritable: false,
438
- });
439
- }
440
- for (const spotPosition of userAccount.spotPositions) {
441
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
442
- const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
443
- spotMarketAccountMap.set(spotPosition.marketIndex, {
444
- pubkey: spotMarketAccount.pubkey,
433
+ if (params.writablePerpMarketIndexes !== undefined) {
434
+ for (const writablePerpMarketIndex of params.writablePerpMarketIndexes) {
435
+ const marketAccount = this.getPerpMarketAccount(writablePerpMarketIndex);
436
+ perpMarketAccountMap.set(writablePerpMarketIndex, {
437
+ pubkey: marketAccount.pubkey,
438
+ isSigner: false,
439
+ isWritable: true,
440
+ });
441
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
442
+ pubkey: marketAccount.amm.oracle,
445
443
  isSigner: false,
446
444
  isWritable: false,
447
445
  });
448
- if (spotMarketAccount.marketIndex !== 0) {
449
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
450
- pubkey: spotMarketAccount.oracle,
451
- isSigner: false,
452
- isWritable: false,
453
- });
454
- }
455
446
  }
456
447
  }
457
448
  if (params.readableSpotMarketIndex !== undefined) {
@@ -469,19 +460,21 @@ class ClearingHouse {
469
460
  });
470
461
  }
471
462
  }
472
- if (params.writableSpotMarketIndex !== undefined) {
473
- const spotMarketAccount = this.getSpotMarketAccount(params.writableSpotMarketIndex);
474
- spotMarketAccountMap.set(params.writableSpotMarketIndex, {
475
- pubkey: spotMarketAccount.pubkey,
476
- isSigner: false,
477
- isWritable: true,
478
- });
479
- if (spotMarketAccount.marketIndex !== 0) {
480
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
481
- pubkey: spotMarketAccount.oracle,
463
+ if (params.writableSpotMarketIndexes !== undefined) {
464
+ for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
465
+ const spotMarketAccount = this.getSpotMarketAccount(writableSpotMarketIndex);
466
+ spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
467
+ pubkey: spotMarketAccount.pubkey,
482
468
  isSigner: false,
483
- isWritable: false,
469
+ isWritable: true,
484
470
  });
471
+ if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
472
+ oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
473
+ pubkey: spotMarketAccount.oracle,
474
+ isSigner: false,
475
+ isWritable: false,
476
+ });
477
+ }
485
478
  }
486
479
  }
487
480
  return [
@@ -490,10 +483,53 @@ class ClearingHouse {
490
483
  ...perpMarketAccountMap.values(),
491
484
  ];
492
485
  }
486
+ getRemainingAccountMapsForUsers(userAccounts) {
487
+ const oracleAccountMap = new Map();
488
+ const spotMarketAccountMap = new Map();
489
+ const perpMarketAccountMap = new Map();
490
+ for (const userAccount of userAccounts) {
491
+ for (const spotPosition of userAccount.spotPositions) {
492
+ if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
493
+ const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
494
+ spotMarketAccountMap.set(spotPosition.marketIndex, {
495
+ pubkey: spotMarket.pubkey,
496
+ isSigner: false,
497
+ isWritable: false,
498
+ });
499
+ if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
500
+ oracleAccountMap.set(spotMarket.oracle.toString(), {
501
+ pubkey: spotMarket.oracle,
502
+ isSigner: false,
503
+ isWritable: false,
504
+ });
505
+ }
506
+ }
507
+ }
508
+ for (const position of userAccount.perpPositions) {
509
+ if (!(0, position_1.positionIsAvailable)(position)) {
510
+ const market = this.getPerpMarketAccount(position.marketIndex);
511
+ perpMarketAccountMap.set(position.marketIndex, {
512
+ pubkey: market.pubkey,
513
+ isWritable: false,
514
+ isSigner: false,
515
+ });
516
+ oracleAccountMap.set(market.amm.oracle.toString(), {
517
+ pubkey: market.amm.oracle,
518
+ isWritable: false,
519
+ isSigner: false,
520
+ });
521
+ }
522
+ }
523
+ }
524
+ return {
525
+ oracleAccountMap,
526
+ spotMarketAccountMap,
527
+ perpMarketAccountMap,
528
+ };
529
+ }
493
530
  getOrder(orderId) {
494
531
  var _a;
495
- const orderIdBN = orderId instanceof anchor_1.BN ? orderId : new anchor_1.BN(orderId);
496
- return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.orderId.eq(orderIdBN));
532
+ return (_a = this.getUserAccount()) === null || _a === void 0 ? void 0 : _a.orders.find((order) => order.orderId === orderId);
497
533
  }
498
534
  getOrderByUserId(userOrderId) {
499
535
  var _a;
@@ -530,22 +566,15 @@ class ClearingHouse {
530
566
  let remainingAccounts = [];
531
567
  if (userInitialized) {
532
568
  remainingAccounts = this.getRemainingAccounts({
533
- writableSpotMarketIndex: marketIndex,
569
+ userAccounts: [this.getUserAccount()],
570
+ useMarketLastSlotCache: true,
571
+ writableSpotMarketIndexes: [marketIndex],
534
572
  });
535
573
  }
536
574
  else {
537
- const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
538
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
539
- remainingAccounts.push({
540
- pubkey: spotMarketAccount.oracle,
541
- isSigner: false,
542
- isWritable: false,
543
- });
544
- }
545
- remainingAccounts.push({
546
- pubkey: spotMarketAccount.pubkey,
547
- isSigner: false,
548
- isWritable: true,
575
+ remainingAccounts = this.getRemainingAccounts({
576
+ userAccounts: [],
577
+ writableSpotMarketIndexes: [marketIndex],
549
578
  });
550
579
  }
551
580
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
@@ -686,7 +715,9 @@ class ClearingHouse {
686
715
  async getWithdrawIx(amount, marketIndex, userTokenAccount, reduceOnly = false) {
687
716
  const userAccountPublicKey = await this.getUserAccountPublicKey();
688
717
  const remainingAccounts = this.getRemainingAccounts({
689
- writableSpotMarketIndex: marketIndex,
718
+ userAccounts: [this.getUserAccount()],
719
+ useMarketLastSlotCache: true,
720
+ writableSpotMarketIndexes: [marketIndex],
690
721
  });
691
722
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
692
723
  return await this.program.instruction.withdraw(marketIndex, amount, reduceOnly, {
@@ -711,9 +742,23 @@ class ClearingHouse {
711
742
  async getTransferDepositIx(amount, marketIndex, fromUserId, toUserId) {
712
743
  const fromUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, fromUserId);
713
744
  const toUser = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, toUserId);
714
- const remainingAccounts = this.getRemainingAccounts({
715
- writableSpotMarketIndex: marketIndex,
716
- });
745
+ let remainingAccounts;
746
+ if (this.users.has(fromUserId)) {
747
+ remainingAccounts = this.getRemainingAccounts({
748
+ userAccounts: [this.users.get(fromUserId).getUserAccount()],
749
+ useMarketLastSlotCache: true,
750
+ writableSpotMarketIndexes: [marketIndex],
751
+ });
752
+ }
753
+ else {
754
+ const userAccountPublicKey = (0, pda_1.getUserAccountPublicKeySync)(this.program.programId, this.authority, fromUserId);
755
+ const fromUserAccount = (await this.program.account.user.fetch(userAccountPublicKey));
756
+ remainingAccounts = this.getRemainingAccounts({
757
+ userAccounts: [fromUserAccount],
758
+ useMarketLastSlotCache: true,
759
+ writableSpotMarketIndexes: [marketIndex],
760
+ });
761
+ }
717
762
  return await this.program.instruction.transferDeposit(marketIndex, amount, {
718
763
  accounts: {
719
764
  authority: this.wallet.publicKey,
@@ -733,6 +778,7 @@ class ClearingHouse {
733
778
  const spotMarket = this.getSpotMarketAccount(marketIndex);
734
779
  return await this.program.instruction.updateSpotMarketCumulativeInterest({
735
780
  accounts: {
781
+ state: await this.getStatePublicKey(),
736
782
  spotMarket: spotMarket.pubkey,
737
783
  },
738
784
  });
@@ -743,25 +789,10 @@ class ClearingHouse {
743
789
  }
744
790
  async settleLPIx(settleeUserAccountPublicKey, marketIndex) {
745
791
  const settleeUserAccount = (await this.program.account.user.fetch(settleeUserAccountPublicKey));
746
- const userPositions = settleeUserAccount.perpPositions;
747
- const remainingAccounts = [];
748
- let foundMarket = false;
749
- for (const position of userPositions) {
750
- if (!(0, position_1.positionIsAvailable)(position)) {
751
- const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
752
- remainingAccounts.push({
753
- pubkey: marketPublicKey,
754
- isWritable: true,
755
- isSigner: false,
756
- });
757
- if (marketIndex === position.marketIndex) {
758
- foundMarket = true;
759
- }
760
- }
761
- }
762
- if (!foundMarket) {
763
- console.log('Warning: lp is not in the market specified -- tx will likely fail');
764
- }
792
+ const remainingAccounts = this.getRemainingAccounts({
793
+ userAccounts: [settleeUserAccount],
794
+ writablePerpMarketIndexes: [marketIndex],
795
+ });
765
796
  return this.program.instruction.settleLp(marketIndex, {
766
797
  accounts: {
767
798
  state: await this.getStatePublicKey(),
@@ -777,7 +808,9 @@ class ClearingHouse {
777
808
  async getRemoveLiquidityIx(marketIndex, sharesToBurn) {
778
809
  const userAccountPublicKey = await this.getUserAccountPublicKey();
779
810
  const remainingAccounts = this.getRemainingAccounts({
780
- writablePerpMarketIndex: marketIndex,
811
+ userAccounts: [this.getUserAccount()],
812
+ useMarketLastSlotCache: true,
813
+ writablePerpMarketIndexes: [marketIndex],
781
814
  });
782
815
  if (sharesToBurn == undefined) {
783
816
  const userAccount = this.getUserAccount();
@@ -802,7 +835,9 @@ class ClearingHouse {
802
835
  async getAddLiquidityIx(amount, marketIndex) {
803
836
  const userAccountPublicKey = await this.getUserAccountPublicKey();
804
837
  const remainingAccounts = this.getRemainingAccounts({
805
- writablePerpMarketIndex: marketIndex,
838
+ userAccounts: [this.getUserAccount()],
839
+ useMarketLastSlotCache: true,
840
+ writablePerpMarketIndexes: [marketIndex],
806
841
  });
807
842
  return this.program.instruction.addLiquidity(amount, marketIndex, {
808
843
  accounts: {
@@ -866,6 +901,8 @@ class ClearingHouse {
866
901
  orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
867
902
  const userAccountPublicKey = await this.getUserAccountPublicKey();
868
903
  const remainingAccounts = this.getRemainingAccounts({
904
+ userAccounts: [this.getUserAccount()],
905
+ useMarketLastSlotCache: true,
869
906
  readablePerpMarketIndex: orderParams.marketIndex,
870
907
  });
871
908
  return await this.program.instruction.placeOrder(orderParams, {
@@ -953,7 +990,10 @@ class ClearingHouse {
953
990
  }
954
991
  async getCancelOrderIx(orderId) {
955
992
  const userAccountPublicKey = await this.getUserAccountPublicKey();
956
- const remainingAccounts = this.getRemainingAccounts({});
993
+ const remainingAccounts = this.getRemainingAccounts({
994
+ userAccounts: [this.getUserAccount()],
995
+ useMarketLastSlotCache: true,
996
+ });
957
997
  return await this.program.instruction.cancelOrder(orderId !== null && orderId !== void 0 ? orderId : null, {
958
998
  accounts: {
959
999
  state: await this.getStatePublicKey(),
@@ -971,7 +1011,10 @@ class ClearingHouse {
971
1011
  const userAccountPublicKey = await this.getUserAccountPublicKey();
972
1012
  const order = this.getOrderByUserId(userOrderId);
973
1013
  const oracle = this.getPerpMarketAccount(order.marketIndex).amm.oracle;
974
- const remainingAccounts = this.getRemainingAccounts({});
1014
+ const remainingAccounts = this.getRemainingAccounts({
1015
+ userAccounts: [this.getUserAccount()],
1016
+ useMarketLastSlotCache: true,
1017
+ });
975
1018
  return await this.program.instruction.cancelOrderByUserId(userOrderId, {
976
1019
  accounts: {
977
1020
  state: await this.getStatePublicKey(),
@@ -992,59 +1035,15 @@ class ClearingHouse {
992
1035
  const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
993
1036
  const marketIndex = order
994
1037
  ? order.marketIndex
995
- : userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
996
- const marketAccount = this.getPerpMarketAccount(marketIndex);
997
- const oracleAccountMap = new Map();
998
- const spotMarketAccountMap = new Map();
999
- const perpMarketAccountMap = new Map();
1000
- for (const spotPosition of userAccount.spotPositions) {
1001
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1002
- const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
1003
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1004
- pubkey: spotMarketAccount.pubkey,
1005
- isSigner: false,
1006
- isWritable: false,
1007
- });
1008
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1009
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1010
- pubkey: spotMarketAccount.oracle,
1011
- isSigner: false,
1012
- isWritable: false,
1013
- });
1014
- }
1015
- }
1016
- }
1017
- for (const position of userAccount.perpPositions) {
1018
- if (!(0, position_1.positionIsAvailable)(position) &&
1019
- position.marketIndex !== order.marketIndex) {
1020
- const market = this.getPerpMarketAccount(position.marketIndex);
1021
- perpMarketAccountMap.set(position.marketIndex, {
1022
- pubkey: market.pubkey,
1023
- isWritable: false,
1024
- isSigner: false,
1025
- });
1026
- oracleAccountMap.set(market.amm.oracle.toString(), {
1027
- pubkey: market.amm.oracle,
1028
- isWritable: false,
1029
- isSigner: false,
1030
- });
1031
- }
1038
+ : userAccount.orders.find((order) => order.orderId === userAccount.nextOrderId - 1).marketIndex;
1039
+ const userAccounts = [userAccount];
1040
+ if (makerInfo !== undefined) {
1041
+ userAccounts.push(makerInfo.makerUserAccount);
1032
1042
  }
1033
- perpMarketAccountMap.set(marketIndex, {
1034
- pubkey: marketAccount.pubkey,
1035
- isWritable: true,
1036
- isSigner: false,
1037
- });
1038
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1039
- pubkey: marketAccount.amm.oracle,
1040
- isWritable: false,
1041
- isSigner: false,
1043
+ const remainingAccounts = this.getRemainingAccounts({
1044
+ userAccounts,
1045
+ writablePerpMarketIndexes: [marketIndex],
1042
1046
  });
1043
- const remainingAccounts = [
1044
- ...oracleAccountMap.values(),
1045
- ...spotMarketAccountMap.values(),
1046
- ...perpMarketAccountMap.values(),
1047
- ];
1048
1047
  if (makerInfo) {
1049
1048
  remainingAccounts.push({
1050
1049
  pubkey: makerInfo.maker,
@@ -1091,6 +1090,8 @@ class ClearingHouse {
1091
1090
  orderParams = this.getOrderParams(orderParams, types_1.MarketType.SPOT);
1092
1091
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1093
1092
  const remainingAccounts = this.getRemainingAccounts({
1093
+ userAccounts: [this.getUserAccount()],
1094
+ useMarketLastSlotCache: true,
1094
1095
  readableSpotMarketIndex: orderParams.marketIndex,
1095
1096
  });
1096
1097
  return await this.program.instruction.placeSpotOrder(orderParams, {
@@ -1113,66 +1114,15 @@ class ClearingHouse {
1113
1114
  const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1114
1115
  const marketIndex = order
1115
1116
  ? order.marketIndex
1116
- : userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
1117
- const oracleAccountMap = new Map();
1118
- const spotMarketAccountMap = new Map();
1119
- const perpMarketAccountMap = new Map();
1120
- for (const spotPosition of userAccount.spotPositions) {
1121
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1122
- const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
1123
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1124
- pubkey: spotMarket.pubkey,
1125
- isSigner: false,
1126
- isWritable: false,
1127
- });
1128
- if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
1129
- oracleAccountMap.set(spotMarket.oracle.toString(), {
1130
- pubkey: spotMarket.oracle,
1131
- isSigner: false,
1132
- isWritable: false,
1133
- });
1134
- }
1135
- }
1136
- }
1137
- for (const position of userAccount.perpPositions) {
1138
- if (!(0, position_1.positionIsAvailable)(position)) {
1139
- const market = this.getPerpMarketAccount(position.marketIndex);
1140
- perpMarketAccountMap.set(position.marketIndex, {
1141
- pubkey: market.pubkey,
1142
- isWritable: false,
1143
- isSigner: false,
1144
- });
1145
- oracleAccountMap.set(market.amm.oracle.toString(), {
1146
- pubkey: market.amm.oracle,
1147
- isWritable: false,
1148
- isSigner: false,
1149
- });
1150
- }
1151
- }
1152
- const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1153
- spotMarketAccountMap.set(marketIndex, {
1154
- pubkey: spotMarketAccount.pubkey,
1155
- isWritable: true,
1156
- isSigner: false,
1157
- });
1158
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1159
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1160
- pubkey: spotMarketAccount.oracle,
1161
- isWritable: false,
1162
- isSigner: false,
1163
- });
1117
+ : userAccount.orders.find((order) => order.orderId === userAccount.nextOrderId - 1).marketIndex;
1118
+ const userAccounts = [userAccount];
1119
+ if (makerInfo !== undefined) {
1120
+ userAccounts.push(makerInfo.makerUserAccount);
1164
1121
  }
1165
- const quoteMarketAccount = this.getQuoteSpotMarketAccount();
1166
- spotMarketAccountMap.set(quoteMarketAccount.marketIndex, {
1167
- pubkey: quoteMarketAccount.pubkey,
1168
- isWritable: true,
1169
- isSigner: false,
1122
+ const remainingAccounts = this.getRemainingAccounts({
1123
+ userAccounts,
1124
+ writableSpotMarketIndexes: [marketIndex, numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1170
1125
  });
1171
- const remainingAccounts = [
1172
- ...oracleAccountMap.values(),
1173
- ...spotMarketAccountMap.values(),
1174
- ...perpMarketAccountMap.values(),
1175
- ];
1176
1126
  if (makerInfo) {
1177
1127
  remainingAccounts.push({
1178
1128
  pubkey: makerInfo.maker,
@@ -1266,12 +1216,12 @@ class ClearingHouse {
1266
1216
  isSigner: false,
1267
1217
  });
1268
1218
  remainingAccounts.push({
1269
- pubkey: spotMarketAccount.vault,
1219
+ pubkey: this.getSpotMarketAccount(marketIndex).vault,
1270
1220
  isWritable: true,
1271
1221
  isSigner: false,
1272
1222
  });
1273
1223
  remainingAccounts.push({
1274
- pubkey: quoteMarketAccount.vault,
1224
+ pubkey: this.getQuoteSpotMarketAccount().vault,
1275
1225
  isWritable: true,
1276
1226
  isSigner: false,
1277
1227
  });
@@ -1299,59 +1249,20 @@ class ClearingHouse {
1299
1249
  }
1300
1250
  async getTriggerOrderIx(userAccountPublicKey, userAccount, order) {
1301
1251
  const fillerPublicKey = await this.getUserAccountPublicKey();
1302
- const marketIndex = order.marketIndex;
1303
- const marketAccount = this.getPerpMarketAccount(marketIndex);
1304
- const oracleAccountMap = new Map();
1305
- const spotMarketAccountMap = new Map();
1306
- const perpMarketAccountMap = new Map();
1307
- for (const spotPosition of userAccount.spotPositions) {
1308
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1309
- const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
1310
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1311
- pubkey: spotMarketAccount.pubkey,
1312
- isSigner: false,
1313
- isWritable: false,
1314
- });
1315
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1316
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1317
- pubkey: spotMarketAccount.oracle,
1318
- isSigner: false,
1319
- isWritable: false,
1320
- });
1321
- }
1322
- }
1252
+ let remainingAccountsParams;
1253
+ if ((0, types_1.isVariant)(order.marketType, 'perp')) {
1254
+ remainingAccountsParams = {
1255
+ userAccounts: [userAccount],
1256
+ writablePerpMarketIndexes: [order.marketIndex],
1257
+ };
1323
1258
  }
1324
- for (const position of userAccount.perpPositions) {
1325
- if (!(0, position_1.positionIsAvailable)(position) &&
1326
- position.marketIndex !== order.marketIndex) {
1327
- const market = this.getPerpMarketAccount(position.marketIndex);
1328
- perpMarketAccountMap.set(position.marketIndex, {
1329
- pubkey: market.pubkey,
1330
- isWritable: false,
1331
- isSigner: false,
1332
- });
1333
- oracleAccountMap.set(market.amm.oracle.toString(), {
1334
- pubkey: market.amm.oracle,
1335
- isWritable: false,
1336
- isSigner: false,
1337
- });
1338
- }
1259
+ else {
1260
+ remainingAccountsParams = {
1261
+ userAccounts: [userAccount],
1262
+ writableSpotMarketIndexes: [order.marketIndex, numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1263
+ };
1339
1264
  }
1340
- perpMarketAccountMap.set(marketIndex, {
1341
- pubkey: marketAccount.pubkey,
1342
- isWritable: true,
1343
- isSigner: false,
1344
- });
1345
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1346
- pubkey: marketAccount.amm.oracle,
1347
- isWritable: false,
1348
- isSigner: false,
1349
- });
1350
- const remainingAccounts = [
1351
- ...oracleAccountMap.values(),
1352
- ...spotMarketAccountMap.values(),
1353
- ...perpMarketAccountMap.values(),
1354
- ];
1265
+ const remainingAccounts = this.getRemainingAccounts(remainingAccountsParams);
1355
1266
  const orderId = order.orderId;
1356
1267
  return await this.program.instruction.triggerOrder(orderId, {
1357
1268
  accounts: {
@@ -1363,82 +1274,6 @@ class ClearingHouse {
1363
1274
  remainingAccounts,
1364
1275
  });
1365
1276
  }
1366
- async triggerSpotOrder(userAccountPublicKey, user, order) {
1367
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getTriggerSpotOrderIx(userAccountPublicKey, user, order)), [], this.opts);
1368
- return txSig;
1369
- }
1370
- async getTriggerSpotOrderIx(userAccountPublicKey, userAccount, order) {
1371
- const fillerPublicKey = await this.getUserAccountPublicKey();
1372
- const marketIndex = order.marketIndex;
1373
- const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
1374
- const oracleAccountMap = new Map();
1375
- const spotMarketAccountMap = new Map();
1376
- const perpMarketAccountMap = new Map();
1377
- for (const spotPosition of userAccount.spotPositions) {
1378
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1379
- const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
1380
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1381
- pubkey: spotMarketAccount.pubkey,
1382
- isSigner: false,
1383
- isWritable: false,
1384
- });
1385
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1386
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1387
- pubkey: spotMarketAccount.oracle,
1388
- isSigner: false,
1389
- isWritable: false,
1390
- });
1391
- }
1392
- }
1393
- }
1394
- for (const position of userAccount.perpPositions) {
1395
- if (!(0, position_1.positionIsAvailable)(position) &&
1396
- position.marketIndex !== order.marketIndex) {
1397
- const market = this.getPerpMarketAccount(position.marketIndex);
1398
- perpMarketAccountMap.set(position.marketIndex, {
1399
- pubkey: market.pubkey,
1400
- isWritable: false,
1401
- isSigner: false,
1402
- });
1403
- oracleAccountMap.set(market.amm.oracle.toString(), {
1404
- pubkey: market.amm.oracle,
1405
- isWritable: false,
1406
- isSigner: false,
1407
- });
1408
- }
1409
- }
1410
- const quoteSpotMarket = this.getQuoteSpotMarketAccount();
1411
- spotMarketAccountMap.set(quoteSpotMarket.marketIndex, {
1412
- pubkey: quoteSpotMarket.pubkey,
1413
- isWritable: true,
1414
- isSigner: false,
1415
- });
1416
- spotMarketAccountMap.set(marketIndex, {
1417
- pubkey: spotMarketAccount.pubkey,
1418
- isWritable: false,
1419
- isSigner: false,
1420
- });
1421
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1422
- pubkey: spotMarketAccount.oracle,
1423
- isWritable: false,
1424
- isSigner: false,
1425
- });
1426
- const remainingAccounts = [
1427
- ...oracleAccountMap.values(),
1428
- ...spotMarketAccountMap.values(),
1429
- ...perpMarketAccountMap.values(),
1430
- ];
1431
- const orderId = order.orderId;
1432
- return await this.program.instruction.triggerSpotOrder(orderId, {
1433
- accounts: {
1434
- state: await this.getStatePublicKey(),
1435
- filler: fillerPublicKey,
1436
- user: userAccountPublicKey,
1437
- authority: this.wallet.publicKey,
1438
- },
1439
- remainingAccounts,
1440
- });
1441
- }
1442
1277
  async placeAndTake(orderParams, makerInfo, referrerInfo) {
1443
1278
  const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
1444
1279
  this.marketLastSlotCache.set(orderParams.marketIndex, slot);
@@ -1448,9 +1283,14 @@ class ClearingHouse {
1448
1283
  orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
1449
1284
  const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
1450
1285
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1286
+ const userAccounts = [this.getUserAccount()];
1287
+ if (makerInfo !== undefined) {
1288
+ userAccounts.push(makerInfo.makerUserAccount);
1289
+ }
1451
1290
  const remainingAccounts = this.getRemainingAccounts({
1452
- writablePerpMarketIndex: orderParams.marketIndex,
1453
- writableSpotMarketIndex: numericConstants_1.QUOTE_SPOT_MARKET_INDEX,
1291
+ userAccounts,
1292
+ useMarketLastSlotCache: true,
1293
+ writablePerpMarketIndexes: [orderParams.marketIndex],
1454
1294
  });
1455
1295
  let makerOrderId = null;
1456
1296
  if (makerInfo) {
@@ -1497,10 +1337,10 @@ class ClearingHouse {
1497
1337
  orderParams = this.getOrderParams(orderParams, types_1.MarketType.PERP);
1498
1338
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1499
1339
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1500
- // todo merge this with getRemainingAccounts
1501
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1502
- counterPartyUserAccount: takerInfo.takerUserAccount,
1503
- writablePerpMarketIndex: orderParams.marketIndex,
1340
+ const remainingAccounts = this.getRemainingAccounts({
1341
+ userAccounts: [this.getUserAccount(), takerInfo.takerUserAccount],
1342
+ useMarketLastSlotCache: true,
1343
+ writablePerpMarketIndexes: [orderParams.marketIndex],
1504
1344
  });
1505
1345
  if (referrerInfo) {
1506
1346
  remainingAccounts.push({
@@ -1565,62 +1405,11 @@ class ClearingHouse {
1565
1405
  return txSig;
1566
1406
  }
1567
1407
  async settlePNLIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
1568
- const perpMarketAccountMap = new Map();
1569
- const oracleAccountMap = new Map();
1570
- const spotMarketAccountMap = new Map();
1571
- for (const position of settleeUserAccount.perpPositions) {
1572
- if (!(0, position_1.positionIsAvailable)(position)) {
1573
- const market = this.getPerpMarketAccount(position.marketIndex);
1574
- perpMarketAccountMap.set(position.marketIndex, {
1575
- pubkey: market.pubkey,
1576
- isWritable: false,
1577
- isSigner: false,
1578
- });
1579
- oracleAccountMap.set(market.amm.oracle.toString(), {
1580
- pubkey: market.amm.oracle,
1581
- isWritable: false,
1582
- isSigner: false,
1583
- });
1584
- }
1585
- }
1586
- for (const spotPosition of settleeUserAccount.spotPositions) {
1587
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1588
- const spotMarketAccount = this.getSpotMarketAccount(spotPosition.marketIndex);
1589
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1590
- pubkey: spotMarketAccount.pubkey,
1591
- isSigner: false,
1592
- isWritable: false,
1593
- });
1594
- if (spotMarketAccount.marketIndex !== 0) {
1595
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1596
- pubkey: spotMarketAccount.oracle,
1597
- isSigner: false,
1598
- isWritable: false,
1599
- });
1600
- }
1601
- }
1602
- }
1603
- const marketAccount = this.getPerpMarketAccount(marketIndex);
1604
- perpMarketAccountMap.set(marketIndex, {
1605
- pubkey: marketAccount.pubkey,
1606
- isSigner: false,
1607
- isWritable: true,
1608
- });
1609
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1610
- pubkey: marketAccount.amm.oracle,
1611
- isSigner: false,
1612
- isWritable: false,
1613
- });
1614
- spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
1615
- pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
1616
- isSigner: false,
1617
- isWritable: true,
1408
+ const remainingAccounts = this.getRemainingAccounts({
1409
+ userAccounts: [settleeUserAccount],
1410
+ writablePerpMarketIndexes: [marketIndex],
1411
+ writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1618
1412
  });
1619
- const remainingAccounts = [
1620
- ...oracleAccountMap.values(),
1621
- ...spotMarketAccountMap.values(),
1622
- ...perpMarketAccountMap.values(),
1623
- ];
1624
1413
  return await this.program.instruction.settlePnl(marketIndex, {
1625
1414
  accounts: {
1626
1415
  state: await this.getStatePublicKey(),
@@ -1635,62 +1424,11 @@ class ClearingHouse {
1635
1424
  return txSig;
1636
1425
  }
1637
1426
  async getSettleExpiredPositionIx(settleeUserAccountPublicKey, settleeUserAccount, marketIndex) {
1638
- const marketAccountMap = new Map();
1639
- const oracleAccountMap = new Map();
1640
- const spotMarketAccountMap = new Map();
1641
- for (const position of settleeUserAccount.perpPositions) {
1642
- if (!(0, position_1.positionIsAvailable)(position)) {
1643
- const market = this.getPerpMarketAccount(position.marketIndex);
1644
- marketAccountMap.set(position.marketIndex, {
1645
- pubkey: market.pubkey,
1646
- isWritable: false,
1647
- isSigner: false,
1648
- });
1649
- oracleAccountMap.set(market.amm.oracle.toString(), {
1650
- pubkey: market.amm.oracle,
1651
- isWritable: false,
1652
- isSigner: false,
1653
- });
1654
- }
1655
- }
1656
- for (const userBankBalance of settleeUserAccount.spotPositions) {
1657
- if (!userBankBalance.balance.eq(numericConstants_1.ZERO)) {
1658
- const bankAccount = this.getSpotMarketAccount(userBankBalance.marketIndex);
1659
- spotMarketAccountMap.set(userBankBalance.marketIndex, {
1660
- pubkey: bankAccount.pubkey,
1661
- isSigner: false,
1662
- isWritable: false,
1663
- });
1664
- if (bankAccount.marketIndex !== 0) {
1665
- oracleAccountMap.set(bankAccount.oracle.toString(), {
1666
- pubkey: bankAccount.oracle,
1667
- isSigner: false,
1668
- isWritable: false,
1669
- });
1670
- }
1671
- }
1672
- }
1673
- const marketAccount = this.getPerpMarketAccount(marketIndex);
1674
- marketAccountMap.set(marketIndex, {
1675
- pubkey: marketAccount.pubkey,
1676
- isSigner: false,
1677
- isWritable: true,
1678
- });
1679
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1680
- pubkey: marketAccount.amm.oracle,
1681
- isSigner: false,
1682
- isWritable: false,
1683
- });
1684
- spotMarketAccountMap.set(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, {
1685
- pubkey: this.getSpotMarketAccount(numericConstants_1.QUOTE_SPOT_MARKET_INDEX).pubkey,
1686
- isSigner: false,
1687
- isWritable: true,
1427
+ const remainingAccounts = this.getRemainingAccounts({
1428
+ userAccounts: [settleeUserAccount],
1429
+ writablePerpMarketIndexes: [marketIndex],
1430
+ writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1688
1431
  });
1689
- const remainingAccounts = [
1690
- ...oracleAccountMap.values(),
1691
- ...spotMarketAccountMap.values(),
1692
- ...marketAccountMap.values(),
1693
- ];
1694
1432
  return await this.program.instruction.settleExpiredPosition(marketIndex, {
1695
1433
  accounts: {
1696
1434
  state: await this.getStatePublicKey(),
@@ -1709,9 +1447,10 @@ class ClearingHouse {
1709
1447
  const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1710
1448
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1711
1449
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
1712
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1713
- writablePerpMarketIndex: marketIndex,
1714
- counterPartyUserAccount: userAccount,
1450
+ const remainingAccounts = this.getRemainingAccounts({
1451
+ userAccounts: [this.getUserAccount(), userAccount],
1452
+ useMarketLastSlotCache: true,
1453
+ writablePerpMarketIndexes: [marketIndex],
1715
1454
  });
1716
1455
  return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
1717
1456
  accounts: {
@@ -1725,22 +1464,27 @@ class ClearingHouse {
1725
1464
  remainingAccounts: remainingAccounts,
1726
1465
  });
1727
1466
  }
1728
- async liquidateBorrow(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1729
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1467
+ async liquidateSpot(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1468
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer)), [], this.opts);
1730
1469
  return txSig;
1731
1470
  }
1732
- async getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1471
+ async getLiquidateSpotIx(userAccountPublicKey, userAccount, assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1472
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1733
1473
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1734
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1735
- counterPartyUserAccount: userAccount,
1474
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1475
+ const remainingAccounts = this.getRemainingAccounts({
1476
+ userAccounts: [this.getUserAccount(), userAccount],
1477
+ useMarketLastSlotCache: true,
1736
1478
  writableSpotMarketIndexes: [liabilityMarketIndex, assetMarketIndex],
1737
1479
  });
1738
- return await this.program.instruction.liquidateBorrow(assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
1480
+ return await this.program.instruction.liquidateSpot(assetMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
1739
1481
  accounts: {
1740
1482
  state: await this.getStatePublicKey(),
1741
1483
  authority: this.wallet.publicKey,
1742
1484
  user: userAccountPublicKey,
1485
+ userStats: userStatsPublicKey,
1743
1486
  liquidator: liquidatorPublicKey,
1487
+ liquidatorStats: liquidatorStatsPublicKey,
1744
1488
  },
1745
1489
  remainingAccounts: remainingAccounts,
1746
1490
  });
@@ -1751,10 +1495,12 @@ class ClearingHouse {
1751
1495
  return txSig;
1752
1496
  }
1753
1497
  async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer) {
1498
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1754
1499
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1755
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1756
- counterPartyUserAccount: userAccount,
1757
- writablePerpMarketIndex: perpMarketIndex,
1500
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1501
+ const remainingAccounts = this.getRemainingAccounts({
1502
+ userAccounts: [this.getUserAccount(), userAccount],
1503
+ writablePerpMarketIndexes: [perpMarketIndex],
1758
1504
  writableSpotMarketIndexes: [liabilityMarketIndex],
1759
1505
  });
1760
1506
  return await this.program.instruction.liquidateBorrowForPerpPnl(perpMarketIndex, liabilityMarketIndex, maxLiabilityTransfer, {
@@ -1762,7 +1508,9 @@ class ClearingHouse {
1762
1508
  state: await this.getStatePublicKey(),
1763
1509
  authority: this.wallet.publicKey,
1764
1510
  user: userAccountPublicKey,
1511
+ userStats: userStatsPublicKey,
1765
1512
  liquidator: liquidatorPublicKey,
1513
+ liquidatorStats: liquidatorStatsPublicKey,
1766
1514
  },
1767
1515
  remainingAccounts: remainingAccounts,
1768
1516
  });
@@ -1773,10 +1521,12 @@ class ClearingHouse {
1773
1521
  return txSig;
1774
1522
  }
1775
1523
  async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetMarketIndex, maxPnlTransfer) {
1524
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1776
1525
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1777
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1778
- counterPartyUserAccount: userAccount,
1779
- writablePerpMarketIndex: perpMarketIndex,
1526
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1527
+ const remainingAccounts = this.getRemainingAccounts({
1528
+ userAccounts: [this.getUserAccount(), userAccount],
1529
+ writablePerpMarketIndexes: [perpMarketIndex],
1780
1530
  writableSpotMarketIndexes: [assetMarketIndex],
1781
1531
  });
1782
1532
  return await this.program.instruction.liquidatePerpPnlForDeposit(perpMarketIndex, assetMarketIndex, maxPnlTransfer, {
@@ -1784,7 +1534,9 @@ class ClearingHouse {
1784
1534
  state: await this.getStatePublicKey(),
1785
1535
  authority: this.wallet.publicKey,
1786
1536
  user: userAccountPublicKey,
1537
+ userStats: userStatsPublicKey,
1787
1538
  liquidator: liquidatorPublicKey,
1539
+ liquidatorStats: liquidatorStatsPublicKey,
1788
1540
  },
1789
1541
  remainingAccounts: remainingAccounts,
1790
1542
  });
@@ -1794,11 +1546,13 @@ class ClearingHouse {
1794
1546
  return txSig;
1795
1547
  }
1796
1548
  async getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1549
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1797
1550
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1798
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1799
- writablePerpMarketIndex: marketIndex,
1551
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1552
+ const remainingAccounts = this.getRemainingAccounts({
1553
+ userAccounts: [this.getUserAccount(), userAccount],
1554
+ writablePerpMarketIndexes: [marketIndex],
1800
1555
  writableSpotMarketIndexes: [numericConstants_1.QUOTE_SPOT_MARKET_INDEX],
1801
- counterPartyUserAccount: userAccount,
1802
1556
  });
1803
1557
  const spotMarket = this.getSpotMarketAccount(marketIndex);
1804
1558
  return await this.program.instruction.resolvePerpBankruptcy(numericConstants_1.QUOTE_SPOT_MARKET_INDEX, marketIndex, {
@@ -1806,7 +1560,9 @@ class ClearingHouse {
1806
1560
  state: await this.getStatePublicKey(),
1807
1561
  authority: this.wallet.publicKey,
1808
1562
  user: userAccountPublicKey,
1563
+ userStats: userStatsPublicKey,
1809
1564
  liquidator: liquidatorPublicKey,
1565
+ liquidatorStats: liquidatorStatsPublicKey,
1810
1566
  spotMarketVault: spotMarket.vault,
1811
1567
  insuranceFundVault: spotMarket.insuranceFundVault,
1812
1568
  clearingHouseSigner: this.getSignerPublicKey(),
@@ -1815,22 +1571,26 @@ class ClearingHouse {
1815
1571
  remainingAccounts: remainingAccounts,
1816
1572
  });
1817
1573
  }
1818
- async resolveBorrowBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
1819
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
1574
+ async resolveSpotBankruptcy(userAccountPublicKey, userAccount, marketIndex) {
1575
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getResolveSpotBankruptcyIx(userAccountPublicKey, userAccount, marketIndex)), [], this.opts);
1820
1576
  return txSig;
1821
1577
  }
1822
- async getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1578
+ async getResolveSpotBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1579
+ const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1823
1580
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1824
- const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1581
+ const liquidatorStatsPublicKey = await this.getUserStatsAccountPublicKey();
1582
+ const remainingAccounts = this.getRemainingAccounts({
1583
+ userAccounts: [this.getUserAccount(), userAccount],
1825
1584
  writableSpotMarketIndexes: [marketIndex],
1826
- counterPartyUserAccount: userAccount,
1827
1585
  });
1828
1586
  const spotMarket = this.getSpotMarketAccount(marketIndex);
1829
- return await this.program.instruction.resolveBorrowBankruptcy(marketIndex, {
1587
+ return await this.program.instruction.resolveSpotBankruptcy(marketIndex, {
1830
1588
  accounts: {
1831
1589
  state: await this.getStatePublicKey(),
1832
1590
  authority: this.wallet.publicKey,
1833
1591
  user: userAccountPublicKey,
1592
+ userStats: userStatsPublicKey,
1593
+ liquidatorStats: liquidatorStatsPublicKey,
1834
1594
  liquidator: liquidatorPublicKey,
1835
1595
  spotMarketVault: spotMarket.vault,
1836
1596
  insuranceFundVault: spotMarket.insuranceFundVault,
@@ -1840,136 +1600,6 @@ class ClearingHouse {
1840
1600
  remainingAccounts: remainingAccounts,
1841
1601
  });
1842
1602
  }
1843
- getRemainingAccountsWithCounterparty(params) {
1844
- const counterPartyUserAccount = params.counterPartyUserAccount;
1845
- const oracleAccountMap = new Map();
1846
- const spotMarketAccountMap = new Map();
1847
- const marketAccountMap = new Map();
1848
- for (const spotPosition of counterPartyUserAccount.spotPositions) {
1849
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1850
- const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
1851
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1852
- pubkey: spotMarket.pubkey,
1853
- isSigner: false,
1854
- isWritable: false,
1855
- });
1856
- if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
1857
- oracleAccountMap.set(spotMarket.oracle.toString(), {
1858
- pubkey: spotMarket.oracle,
1859
- isSigner: false,
1860
- isWritable: false,
1861
- });
1862
- }
1863
- }
1864
- }
1865
- for (const position of counterPartyUserAccount.perpPositions) {
1866
- if (!(0, position_1.positionIsAvailable)(position)) {
1867
- const market = this.getPerpMarketAccount(position.marketIndex);
1868
- marketAccountMap.set(position.marketIndex, {
1869
- pubkey: market.pubkey,
1870
- isWritable: false,
1871
- isSigner: false,
1872
- });
1873
- oracleAccountMap.set(market.amm.oracle.toString(), {
1874
- pubkey: market.amm.oracle,
1875
- isWritable: false,
1876
- isSigner: false,
1877
- });
1878
- }
1879
- }
1880
- const userAccountAndSlot = this.getUserAccountAndSlot();
1881
- if (!userAccountAndSlot) {
1882
- throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
1883
- }
1884
- const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
1885
- for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
1886
- // if cache has more recent slot than user positions account slot, add market to remaining accounts
1887
- // otherwise remove from slot
1888
- if (slot > lastUserPositionsSlot) {
1889
- const marketAccount = this.getPerpMarketAccount(marketIndexNum);
1890
- marketAccountMap.set(marketIndexNum, {
1891
- pubkey: marketAccount.pubkey,
1892
- isSigner: false,
1893
- isWritable: false,
1894
- });
1895
- oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1896
- pubkey: marketAccount.amm.oracle,
1897
- isSigner: false,
1898
- isWritable: false,
1899
- });
1900
- }
1901
- else {
1902
- this.marketLastSlotCache.delete(marketIndexNum);
1903
- }
1904
- }
1905
- for (const spotPosition of userAccount.spotPositions) {
1906
- if (!(0, spotPosition_1.isSpotPositionAvailable)(spotPosition)) {
1907
- const spotMarket = this.getSpotMarketAccount(spotPosition.marketIndex);
1908
- spotMarketAccountMap.set(spotPosition.marketIndex, {
1909
- pubkey: spotMarket.pubkey,
1910
- isSigner: false,
1911
- isWritable: false,
1912
- });
1913
- if (!spotMarket.oracle.equals(web3_js_1.PublicKey.default)) {
1914
- oracleAccountMap.set(spotMarket.oracle.toString(), {
1915
- pubkey: spotMarket.oracle,
1916
- isSigner: false,
1917
- isWritable: false,
1918
- });
1919
- }
1920
- }
1921
- }
1922
- for (const position of userAccount.perpPositions) {
1923
- if (!(0, position_1.positionIsAvailable)(position)) {
1924
- const market = this.getPerpMarketAccount(position.marketIndex);
1925
- marketAccountMap.set(position.marketIndex, {
1926
- pubkey: market.pubkey,
1927
- isWritable: false,
1928
- isSigner: false,
1929
- });
1930
- oracleAccountMap.set(market.amm.oracle.toString(), {
1931
- pubkey: market.amm.oracle,
1932
- isWritable: false,
1933
- isSigner: false,
1934
- });
1935
- }
1936
- }
1937
- if (params.writablePerpMarketIndex !== undefined) {
1938
- const market = this.getPerpMarketAccount(params.writablePerpMarketIndex);
1939
- marketAccountMap.set(market.marketIndex, {
1940
- pubkey: market.pubkey,
1941
- isSigner: false,
1942
- isWritable: true,
1943
- });
1944
- oracleAccountMap.set(market.amm.oracle.toString(), {
1945
- pubkey: market.amm.oracle,
1946
- isSigner: false,
1947
- isWritable: false,
1948
- });
1949
- }
1950
- if (params.writableSpotMarketIndexes !== undefined) {
1951
- for (const writableSpotMarketIndex of params.writableSpotMarketIndexes) {
1952
- const spotMarketAccount = this.getSpotMarketAccount(writableSpotMarketIndex);
1953
- spotMarketAccountMap.set(spotMarketAccount.marketIndex, {
1954
- pubkey: spotMarketAccount.pubkey,
1955
- isSigner: false,
1956
- isWritable: true,
1957
- });
1958
- if (!spotMarketAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1959
- oracleAccountMap.set(spotMarketAccount.oracle.toString(), {
1960
- pubkey: spotMarketAccount.oracle,
1961
- isSigner: false,
1962
- isWritable: false,
1963
- });
1964
- }
1965
- }
1966
- }
1967
- return [
1968
- ...oracleAccountMap.values(),
1969
- ...spotMarketAccountMap.values(),
1970
- ...marketAccountMap.values(),
1971
- ];
1972
- }
1973
1603
  async updateFundingRate(oracle, marketIndex) {
1974
1604
  const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
1975
1605
  return txSig;
@@ -1983,28 +1613,26 @@ class ClearingHouse {
1983
1613
  },
1984
1614
  });
1985
1615
  }
1986
- async settleFundingPayment(userAccount) {
1987
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleFundingPaymentIx(userAccount)), [], this.opts);
1616
+ async settleFundingPayment(userAccountPublicKey) {
1617
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getSettleFundingPaymentIx(userAccountPublicKey)), [], this.opts);
1988
1618
  return txSig;
1989
1619
  }
1990
- async getSettleFundingPaymentIx(userAccount) {
1991
- const user = (await this.program.account.user.fetch(userAccount));
1992
- const userPositions = user.perpPositions;
1993
- const remainingAccounts = [];
1994
- for (const position of userPositions) {
1620
+ async getSettleFundingPaymentIx(userAccountPublicKey) {
1621
+ const userAccount = (await this.program.account.user.fetch(userAccountPublicKey));
1622
+ const writablePerpMarketIndexes = [];
1623
+ for (const position of userAccount.perpPositions) {
1995
1624
  if (!(0, position_1.positionIsAvailable)(position)) {
1996
- const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
1997
- remainingAccounts.push({
1998
- pubkey: marketPublicKey,
1999
- isWritable: false,
2000
- isSigner: false,
2001
- });
1625
+ writablePerpMarketIndexes.push(position.marketIndex);
2002
1626
  }
2003
1627
  }
1628
+ const remainingAccounts = this.getRemainingAccounts({
1629
+ userAccounts: [userAccount],
1630
+ writablePerpMarketIndexes,
1631
+ });
2004
1632
  return await this.program.instruction.settleFundingPayment({
2005
1633
  accounts: {
2006
1634
  state: await this.getStatePublicKey(),
2007
- user: userAccount,
1635
+ user: userAccountPublicKey,
2008
1636
  },
2009
1637
  remainingAccounts,
2010
1638
  });
@@ -2045,7 +1673,9 @@ class ClearingHouse {
2045
1673
  const spotMarket = this.getSpotMarketAccount(marketIndex);
2046
1674
  const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
2047
1675
  const remainingAccounts = this.getRemainingAccounts({
2048
- writableSpotMarketIndex: marketIndex,
1676
+ userAccounts: [this.getUserAccount()],
1677
+ useMarketLastSlotCache: true,
1678
+ writableSpotMarketIndexes: [marketIndex],
2049
1679
  });
2050
1680
  return await this.program.rpc.addInsuranceFundStake(marketIndex, amount, {
2051
1681
  accounts: {
@@ -2054,7 +1684,9 @@ class ClearingHouse {
2054
1684
  insuranceFundStake: ifStakeAccountPublicKey,
2055
1685
  userStats: this.getUserStatsAccountPublicKey(),
2056
1686
  authority: this.wallet.publicKey,
1687
+ spotMarketVault: spotMarket.vault,
2057
1688
  insuranceFundVault: spotMarket.insuranceFundVault,
1689
+ clearingHouseSigner: this.getSignerPublicKey(),
2058
1690
  userTokenAccount: collateralAccountPublicKey,
2059
1691
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
2060
1692
  },
@@ -2065,7 +1697,9 @@ class ClearingHouse {
2065
1697
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2066
1698
  const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
2067
1699
  const remainingAccounts = this.getRemainingAccounts({
2068
- writableSpotMarketIndex: marketIndex,
1700
+ userAccounts: [this.getUserAccount()],
1701
+ useMarketLastSlotCache: true,
1702
+ writableSpotMarketIndexes: [marketIndex],
2069
1703
  });
2070
1704
  return await this.program.rpc.requestRemoveInsuranceFundStake(marketIndex, amount, {
2071
1705
  accounts: {
@@ -2075,8 +1709,6 @@ class ClearingHouse {
2075
1709
  userStats: this.getUserStatsAccountPublicKey(),
2076
1710
  authority: this.wallet.publicKey,
2077
1711
  insuranceFundVault: spotMarketAccount.insuranceFundVault,
2078
- // userTokenAccount: collateralAccountPublicKey,
2079
- // tokenProgram: TOKEN_PROGRAM_ID,
2080
1712
  },
2081
1713
  remainingAccounts,
2082
1714
  });
@@ -2085,7 +1717,9 @@ class ClearingHouse {
2085
1717
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2086
1718
  const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
2087
1719
  const remainingAccounts = this.getRemainingAccounts({
2088
- writableSpotMarketIndex: marketIndex,
1720
+ userAccounts: [this.getUserAccount()],
1721
+ useMarketLastSlotCache: true,
1722
+ writableSpotMarketIndexes: [marketIndex],
2089
1723
  });
2090
1724
  return await this.program.rpc.cancelRequestRemoveInsuranceFundStake(marketIndex, {
2091
1725
  accounts: {
@@ -2095,8 +1729,6 @@ class ClearingHouse {
2095
1729
  userStats: this.getUserStatsAccountPublicKey(),
2096
1730
  authority: this.wallet.publicKey,
2097
1731
  insuranceFundVault: spotMarketAccount.insuranceFundVault,
2098
- // userTokenAccount: collateralAccountPublicKey,
2099
- // tokenProgram: TOKEN_PROGRAM_ID,
2100
1732
  },
2101
1733
  remainingAccounts,
2102
1734
  });
@@ -2105,7 +1737,9 @@ class ClearingHouse {
2105
1737
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2106
1738
  const ifStakeAccountPublicKey = (0, pda_1.getInsuranceFundStakeAccountPublicKey)(this.program.programId, this.wallet.publicKey, marketIndex);
2107
1739
  const remainingAccounts = this.getRemainingAccounts({
2108
- writableSpotMarketIndex: marketIndex,
1740
+ userAccounts: [this.getUserAccount()],
1741
+ useMarketLastSlotCache: true,
1742
+ writableSpotMarketIndexes: [marketIndex],
2109
1743
  });
2110
1744
  return await this.program.rpc.removeInsuranceFundStake(marketIndex, {
2111
1745
  accounts: {
@@ -2125,7 +1759,9 @@ class ClearingHouse {
2125
1759
  async settleRevenueToInsuranceFund(marketIndex) {
2126
1760
  const spotMarketAccount = this.getSpotMarketAccount(marketIndex);
2127
1761
  const remainingAccounts = this.getRemainingAccounts({
2128
- writableSpotMarketIndex: marketIndex,
1762
+ userAccounts: [this.getUserAccount()],
1763
+ useMarketLastSlotCache: true,
1764
+ writableSpotMarketIndexes: [marketIndex],
2129
1765
  });
2130
1766
  return await this.program.rpc.settleRevenueToInsuranceFund(marketIndex, {
2131
1767
  accounts: {
@@ -2145,8 +1781,10 @@ class ClearingHouse {
2145
1781
  }
2146
1782
  async getResolvePerpPnlDeficitIx(spotMarketIndex, perpMarketIndex) {
2147
1783
  const remainingAccounts = this.getRemainingAccounts({
2148
- writablePerpMarketIndex: perpMarketIndex,
2149
- writableSpotMarketIndex: spotMarketIndex,
1784
+ userAccounts: [this.getUserAccount()],
1785
+ useMarketLastSlotCache: true,
1786
+ writablePerpMarketIndexes: [perpMarketIndex],
1787
+ writableSpotMarketIndexes: [spotMarketIndex],
2150
1788
  });
2151
1789
  const spotMarket = this.getSpotMarketAccount(spotMarketIndex);
2152
1790
  return await this.program.instruction.resolvePerpPnlDeficit(spotMarketIndex, perpMarketIndex, {