@drift-labs/sdk 0.2.0-master.19 → 0.2.0-master.21

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 (86) hide show
  1. package/lib/accounts/types.d.ts +0 -1
  2. package/lib/clearingHouse.d.ts +13 -13
  3. package/lib/clearingHouse.js +98 -37
  4. package/lib/clearingHouseUser.d.ts +9 -1
  5. package/lib/clearingHouseUser.js +64 -45
  6. package/lib/clearingHouseUserStats.d.ts +2 -1
  7. package/lib/clearingHouseUserStats.js +13 -0
  8. package/lib/config.js +1 -1
  9. package/lib/events/types.d.ts +2 -1
  10. package/lib/events/types.js +1 -0
  11. package/lib/idl/clearing_house.json +200 -129
  12. package/lib/index.d.ts +0 -1
  13. package/lib/index.js +0 -1
  14. package/lib/math/amm.d.ts +1 -0
  15. package/lib/math/amm.js +13 -1
  16. package/lib/math/market.d.ts +1 -1
  17. package/lib/math/market.js +5 -5
  18. package/lib/math/orders.d.ts +4 -0
  19. package/lib/math/orders.js +45 -2
  20. package/lib/types.d.ts +28 -7
  21. package/my-script/.env +7 -0
  22. package/my-script/getUserStats.ts +124 -0
  23. package/my-script/multiConnections.ts +137 -0
  24. package/my-script/test-regex.ts +11 -0
  25. package/my-script/utils.ts +52 -0
  26. package/my-script/ww18NdhuLSQPCrHSx7V68eZJpe2y311heWeXJfSmP3Q.json +1 -0
  27. package/my-script/ww2z7N9TG1PLLUQGQF2VKzCFaPtQ5FBhRfeEAuy6c5C.json +1 -0
  28. package/my-script/ww3StJtTubhwssqAhvSSAc5ifCgKjzmF8hz7Gt2DmSa.json +1 -0
  29. package/package.json +1 -1
  30. package/src/clearingHouse.ts +132 -42
  31. package/src/clearingHouseUser.ts +78 -91
  32. package/src/clearingHouseUserStats.ts +23 -1
  33. package/src/config.ts +1 -1
  34. package/src/events/types.ts +3 -0
  35. package/src/idl/clearing_house.json +200 -129
  36. package/src/index.ts +0 -1
  37. package/src/math/amm.ts +27 -1
  38. package/src/math/market.ts +6 -6
  39. package/src/math/orders.ts +114 -2
  40. package/src/types.ts +30 -7
  41. package/lib/orders.d.ts +0 -7
  42. package/lib/orders.js +0 -59
  43. package/src/addresses/marketAddresses.js +0 -26
  44. package/src/assert/assert.js +0 -9
  45. package/src/constants/banks.js +0 -42
  46. package/src/constants/markets.js +0 -42
  47. package/src/constants/numericConstants.js +0 -41
  48. package/src/events/eventList.js +0 -77
  49. package/src/events/eventSubscriber.js +0 -139
  50. package/src/events/fetchLogs.js +0 -50
  51. package/src/events/pollingLogProvider.js +0 -64
  52. package/src/events/sort.js +0 -44
  53. package/src/events/txEventCache.js +0 -71
  54. package/src/events/types.js +0 -20
  55. package/src/events/webSocketLogProvider.js +0 -41
  56. package/src/examples/makeTradeExample.js +0 -80
  57. package/src/factory/bigNum.js +0 -390
  58. package/src/factory/oracleClient.js +0 -20
  59. package/src/math/amm.js +0 -369
  60. package/src/math/auction.js +0 -42
  61. package/src/math/conversion.js +0 -11
  62. package/src/math/funding.js +0 -248
  63. package/src/math/oracles.js +0 -26
  64. package/src/math/repeg.js +0 -128
  65. package/src/math/state.js +0 -15
  66. package/src/math/trade.js +0 -253
  67. package/src/math/utils.js +0 -26
  68. package/src/math/utils.js.map +0 -1
  69. package/src/oracles/oracleClientCache.js +0 -19
  70. package/src/oracles/pythClient.js +0 -46
  71. package/src/oracles/quoteAssetOracleClient.js +0 -32
  72. package/src/oracles/switchboardClient.js +0 -69
  73. package/src/oracles/types.js +0 -2
  74. package/src/orderParams.js +0 -20
  75. package/src/orders.ts +0 -91
  76. package/src/slot/SlotSubscriber.js +0 -39
  77. package/src/token/index.js +0 -38
  78. package/src/tokenFaucet.js +0 -189
  79. package/src/tx/types.js +0 -2
  80. package/src/tx/utils.js +0 -17
  81. package/src/userName.js +0 -20
  82. package/src/util/computeUnits.js +0 -27
  83. package/src/util/getTokenAddress.js +0 -9
  84. package/src/util/promiseTimeout.js +0 -14
  85. package/src/util/tps.js +0 -27
  86. package/src/wallet.js +0 -35
@@ -1,6 +1,5 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="bn.js" />
3
- /// <reference types="node" />
4
3
  import { BankAccount, MarketAccount, OracleSource, StateAccount, UserAccount, UserStatsAccount } from '../types';
5
4
  import StrictEventEmitter from 'strict-event-emitter-types';
6
5
  import { EventEmitter } from 'events';
@@ -1,7 +1,7 @@
1
1
  /// <reference types="node" />
2
2
  /// <reference types="bn.js" />
3
3
  import { AnchorProvider, BN, Program } from '@project-serum/anchor';
4
- import { StateAccount, IWallet, PositionDirection, UserAccount, MarketAccount, OrderParams, Order, BankAccount, UserBankBalance, MakerInfo, TakerInfo, OptionalOrderParams } from './types';
4
+ import { StateAccount, IWallet, PositionDirection, UserAccount, MarketAccount, OrderParams, Order, BankAccount, UserBankBalance, MakerInfo, TakerInfo, OptionalOrderParams, ReferrerInfo } from './types';
5
5
  import { Connection, PublicKey, TransactionSignature, ConfirmOptions, TransactionInstruction, AccountMeta } from '@solana/web3.js';
6
6
  import { TokenFaucet } from './tokenFaucet';
7
7
  import { EventEmitter } from 'events';
@@ -62,8 +62,8 @@ export declare class ClearingHouse {
62
62
  updateWallet(newWallet: IWallet, userIds?: number[], activeUserId?: number): Promise<void>;
63
63
  switchActiveUser(userId: number): Promise<void>;
64
64
  addUser(userId: number): Promise<void>;
65
- initializeUserAccount(userId?: number, name?: string): Promise<[TransactionSignature, PublicKey]>;
66
- getInitializeUserInstructions(userId?: number, name?: string): Promise<[PublicKey, TransactionInstruction]>;
65
+ initializeUserAccount(userId?: number, name?: string, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
66
+ getInitializeUserInstructions(userId?: number, name?: string, referrerInfo?: ReferrerInfo): Promise<[PublicKey, TransactionInstruction]>;
67
67
  getInitializeUserStatsIx(): Promise<TransactionInstruction>;
68
68
  getUser(userId?: number): ClearingHouseUser;
69
69
  getUsers(): ClearingHouseUser[];
@@ -97,8 +97,8 @@ export declare class ClearingHouse {
97
97
  * @param fromUserId
98
98
  * @returns
99
99
  */
100
- initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, bankIndex?: BN, userId?: number, name?: string, fromUserId?: number): Promise<[TransactionSignature, PublicKey]>;
101
- initializeUserAccountForDevnet(userId: number, name: string, bankIndex: BN, tokenFaucet: TokenFaucet, amount: BN): Promise<[TransactionSignature, PublicKey]>;
100
+ initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, bankIndex?: BN, userId?: number, name?: string, fromUserId?: number, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
101
+ initializeUserAccountForDevnet(userId: number, name: string, bankIndex: BN, tokenFaucet: TokenFaucet, amount: BN, referrerInfo?: ReferrerInfo): Promise<[TransactionSignature, PublicKey]>;
102
102
  withdraw(amount: BN, bankIndex: BN, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionSignature>;
103
103
  getWithdrawIx(amount: BN, bankIndex: BN, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionInstruction>;
104
104
  transferDeposit(amount: BN, bankIndex: BN, fromUserId: number, toUserId: number): Promise<TransactionSignature>;
@@ -121,14 +121,14 @@ export declare class ClearingHouse {
121
121
  getCancelOrderIx(orderId?: BN): Promise<TransactionInstruction>;
122
122
  cancelOrderByUserId(userOrderId: number): Promise<TransactionSignature>;
123
123
  getCancelOrderByUserIdIx(userOrderId: number): Promise<TransactionInstruction>;
124
- fillOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, makerInfo?: MakerInfo): Promise<TransactionSignature>;
125
- getFillOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order, makerInfo?: MakerInfo): Promise<TransactionInstruction>;
124
+ fillOrder(userAccountPublicKey: PublicKey, user: UserAccount, order?: Order, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
125
+ getFillOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
126
126
  triggerOrder(userAccountPublicKey: PublicKey, user: UserAccount, order: Order): Promise<TransactionSignature>;
127
127
  getTriggerOrderIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, order: Order): Promise<TransactionInstruction>;
128
- placeAndTake(orderParams: OptionalOrderParams, makerInfo?: MakerInfo): Promise<TransactionSignature>;
129
- getPlaceAndTakeIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo): Promise<TransactionInstruction>;
130
- placeAndMake(orderParams: OptionalOrderParams, takerInfo: TakerInfo): Promise<TransactionSignature>;
131
- getPlaceAndMakeIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo): Promise<TransactionInstruction>;
128
+ placeAndTake(orderParams: OptionalOrderParams, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
129
+ getPlaceAndTakeIx(orderParams: OptionalOrderParams, makerInfo?: MakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
130
+ placeAndMake(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionSignature>;
131
+ getPlaceAndMakeIx(orderParams: OptionalOrderParams, takerInfo: TakerInfo, referrerInfo?: ReferrerInfo): Promise<TransactionInstruction>;
132
132
  /**
133
133
  * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
134
134
  * @param marketIndex
@@ -153,8 +153,8 @@ export declare class ClearingHouse {
153
153
  getResolvePerpBankruptcyIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: BN): Promise<TransactionInstruction>;
154
154
  resolveBorrowBankruptcy(userAccountPublicKey: PublicKey, userAccount: UserAccount, bankIndex: BN): Promise<TransactionSignature>;
155
155
  getResolveBorrowBankruptcyIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, bankIndex: BN): Promise<TransactionInstruction>;
156
- getRemainingAccountsForLiquidation(params: {
157
- userAccount: UserAccount;
156
+ getRemainingAccountsWithCounterparty(params: {
157
+ counterPartyUserAccount: UserAccount;
158
158
  writableMarketIndex?: BN;
159
159
  writableBankIndexes?: BN[];
160
160
  }): AccountMeta[];
@@ -133,9 +133,13 @@ class ClearingHouse {
133
133
  * Forces the accountSubscriber to fetch account updates from rpc
134
134
  */
135
135
  async fetchAccounts() {
136
- await Promise.all([...this.users.values()]
136
+ const promises = [...this.users.values()]
137
137
  .map((user) => user.fetchAccounts())
138
- .concat(this.accountSubscriber.fetch()));
138
+ .concat(this.accountSubscriber.fetch());
139
+ if (this.userStats) {
140
+ promises.concat(this.userStats.fetchAccounts());
141
+ }
142
+ await Promise.all(promises);
139
143
  }
140
144
  async unsubscribe() {
141
145
  const unsubscribePromises = this.unsubscribeUsers().concat(this.accountSubscriber.unsubscribe());
@@ -215,8 +219,8 @@ class ClearingHouse {
215
219
  await user.subscribe();
216
220
  this.users.set(userId, user);
217
221
  }
218
- async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
219
- const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
222
+ async initializeUserAccount(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
223
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
220
224
  const tx = new web3_js_1.Transaction();
221
225
  if (userId === 0) {
222
226
  // not the safest assumption, can explicitly check if user stats account exists if it causes problems
@@ -226,8 +230,21 @@ class ClearingHouse {
226
230
  const { txSig } = await this.txSender.send(tx, [], this.opts);
227
231
  return [txSig, userAccountPublicKey];
228
232
  }
229
- async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME) {
233
+ async getInitializeUserInstructions(userId = 0, name = userName_1.DEFAULT_USER_NAME, referrerInfo) {
230
234
  const userAccountPublicKey = await (0, pda_1.getUserAccountPublicKey)(this.program.programId, this.wallet.publicKey, userId);
235
+ const remainingAccounts = new Array();
236
+ if (referrerInfo !== undefined) {
237
+ remainingAccounts.push({
238
+ pubkey: referrerInfo.referrer,
239
+ isWritable: true,
240
+ isSigner: false,
241
+ });
242
+ remainingAccounts.push({
243
+ pubkey: referrerInfo.referrerStats,
244
+ isWritable: true,
245
+ isSigner: false,
246
+ });
247
+ }
231
248
  const nameBuffer = (0, userName_1.encodeName)(name);
232
249
  const initializeUserAccountIx = await this.program.instruction.initializeUser(userId, nameBuffer, {
233
250
  accounts: {
@@ -239,6 +256,7 @@ class ClearingHouse {
239
256
  systemProgram: anchor.web3.SystemProgram.programId,
240
257
  state: await this.getStatePublicKey(),
241
258
  },
259
+ remainingAccounts,
242
260
  });
243
261
  return [userAccountPublicKey, initializeUserAccountIx];
244
262
  }
@@ -466,6 +484,7 @@ class ClearingHouse {
466
484
  bank: bank.pubkey,
467
485
  bankVault: bank.vault,
468
486
  user: userAccountPublicKey,
487
+ userStats: this.getUserStatsAccountPublicKey(),
469
488
  userTokenAccount: userTokenAccount,
470
489
  authority: this.wallet.publicKey,
471
490
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
@@ -535,8 +554,8 @@ class ClearingHouse {
535
554
  * @param fromUserId
536
555
  * @returns
537
556
  */
538
- async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId) {
539
- const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
557
+ async initializeUserAccountAndDepositCollateral(amount, userTokenAccount, bankIndex = new anchor_1.BN(0), userId = 0, name = userName_1.DEFAULT_USER_NAME, fromUserId, referrerInfo) {
558
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
540
559
  const additionalSigners = [];
541
560
  const bank = this.getBankAccount(bankIndex);
542
561
  const isSolBank = bank.mint.equals(banks_1.WRAPPED_SOL_MINT);
@@ -565,9 +584,9 @@ class ClearingHouse {
565
584
  const { txSig } = await this.txSender.send(tx, additionalSigners, this.opts);
566
585
  return [txSig, userAccountPublicKey];
567
586
  }
568
- async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, bankIndex, tokenFaucet, amount) {
587
+ async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, bankIndex, tokenFaucet, amount, referrerInfo) {
569
588
  const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
570
- const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
589
+ const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name, referrerInfo);
571
590
  const depositCollateralIx = await this.getDepositInstruction(amount, bankIndex, associateTokenPublicKey, userId, false, false);
572
591
  const tx = new web3_js_1.Transaction().add(createAssociatedAccountIx).add(mintToIx);
573
592
  if (userId === 0) {
@@ -614,6 +633,7 @@ class ClearingHouse {
614
633
  bankVault: bank.vault,
615
634
  bankVaultAuthority: bank.vaultAuthority,
616
635
  user: userAccountPublicKey,
636
+ userStats: this.getUserStatsAccountPublicKey(),
617
637
  userTokenAccount: userTokenAccount,
618
638
  authority: this.wallet.publicKey,
619
639
  tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
@@ -636,6 +656,7 @@ class ClearingHouse {
636
656
  authority: this.wallet.publicKey,
637
657
  fromUser,
638
658
  toUser,
659
+ userStats: this.getUserStatsAccountPublicKey(),
639
660
  state: await this.getStatePublicKey(),
640
661
  },
641
662
  remainingAccounts,
@@ -831,15 +852,17 @@ class ClearingHouse {
831
852
  remainingAccounts,
832
853
  });
833
854
  }
834
- async fillOrder(userAccountPublicKey, user, order, makerInfo) {
835
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)), [], this.opts);
855
+ async fillOrder(userAccountPublicKey, user, order, makerInfo, referrerInfo) {
856
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo, referrerInfo)), [], this.opts);
836
857
  return txSig;
837
858
  }
838
- async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo) {
859
+ async getFillOrderIx(userAccountPublicKey, userAccount, order, makerInfo, referrerInfo) {
839
860
  const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
840
861
  const fillerPublicKey = await this.getUserAccountPublicKey();
841
862
  const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
842
- const marketIndex = order.marketIndex;
863
+ const marketIndex = order
864
+ ? order.marketIndex
865
+ : userAccount.orders.find((order) => order.orderId.eq(userAccount.nextOrderId.sub(numericConstants_1.ONE))).marketIndex;
843
866
  const marketAccount = this.getMarketAccount(marketIndex);
844
867
  const oracleAccountMap = new Map();
845
868
  const bankAccountMap = new Map();
@@ -904,6 +927,18 @@ class ClearingHouse {
904
927
  isSigner: false,
905
928
  });
906
929
  }
930
+ if (referrerInfo) {
931
+ remainingAccounts.push({
932
+ pubkey: referrerInfo.referrer,
933
+ isWritable: true,
934
+ isSigner: false,
935
+ });
936
+ remainingAccounts.push({
937
+ pubkey: referrerInfo.referrerStats,
938
+ isWritable: true,
939
+ isSigner: false,
940
+ });
941
+ }
907
942
  const orderId = order.orderId;
908
943
  const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
909
944
  return await this.program.instruction.fillOrder(orderId, makerOrderId, {
@@ -988,12 +1023,12 @@ class ClearingHouse {
988
1023
  remainingAccounts,
989
1024
  });
990
1025
  }
991
- async placeAndTake(orderParams, makerInfo) {
992
- const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo)), [], this.opts);
1026
+ async placeAndTake(orderParams, makerInfo, referrerInfo) {
1027
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)), [], this.opts);
993
1028
  this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
994
1029
  return txSig;
995
1030
  }
996
- async getPlaceAndTakeIx(orderParams, makerInfo) {
1031
+ async getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo) {
997
1032
  orderParams = this.getOrderParams(orderParams);
998
1033
  const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
999
1034
  const userAccountPublicKey = await this.getUserAccountPublicKey();
@@ -1015,6 +1050,18 @@ class ClearingHouse {
1015
1050
  isWritable: true,
1016
1051
  });
1017
1052
  }
1053
+ if (referrerInfo) {
1054
+ remainingAccounts.push({
1055
+ pubkey: referrerInfo.referrer,
1056
+ isWritable: true,
1057
+ isSigner: false,
1058
+ });
1059
+ remainingAccounts.push({
1060
+ pubkey: referrerInfo.referrerStats,
1061
+ isWritable: true,
1062
+ isSigner: false,
1063
+ });
1064
+ }
1018
1065
  return await this.program.instruction.placeAndTake(orderParams, makerOrderId, {
1019
1066
  accounts: {
1020
1067
  state: await this.getStatePublicKey(),
@@ -1025,18 +1072,32 @@ class ClearingHouse {
1025
1072
  remainingAccounts,
1026
1073
  });
1027
1074
  }
1028
- async placeAndMake(orderParams, takerInfo) {
1029
- const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo)), [], this.opts);
1075
+ async placeAndMake(orderParams, takerInfo, referrerInfo) {
1076
+ const { txSig, slot } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)), [], this.opts);
1030
1077
  this.marketLastSlotCache.set(orderParams.marketIndex.toNumber(), slot);
1031
1078
  return txSig;
1032
1079
  }
1033
- async getPlaceAndMakeIx(orderParams, takerInfo) {
1080
+ async getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo) {
1034
1081
  orderParams = this.getOrderParams(orderParams);
1035
1082
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1036
1083
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1037
- const remainingAccounts = this.getRemainingAccounts({
1084
+ // todo merge this with getRemainingAccounts
1085
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1086
+ counterPartyUserAccount: takerInfo.takerUserAccount,
1038
1087
  writableMarketIndex: orderParams.marketIndex,
1039
1088
  });
1089
+ if (referrerInfo) {
1090
+ remainingAccounts.push({
1091
+ pubkey: referrerInfo.referrer,
1092
+ isWritable: true,
1093
+ isSigner: false,
1094
+ });
1095
+ remainingAccounts.push({
1096
+ pubkey: referrerInfo.referrerStats,
1097
+ isWritable: true,
1098
+ isSigner: false,
1099
+ });
1100
+ }
1040
1101
  const takerOrderId = takerInfo.order.orderId;
1041
1102
  return await this.program.instruction.placeAndMake(orderParams, takerOrderId, {
1042
1103
  accounts: {
@@ -1076,7 +1137,7 @@ class ClearingHouse {
1076
1137
  }
1077
1138
  const tx = new web3_js_1.Transaction()
1078
1139
  .add(web3_js_1.ComputeBudgetProgram.requestUnits({
1079
- units: 1200000,
1140
+ units: 1000000,
1080
1141
  additionalFee: 0,
1081
1142
  }))
1082
1143
  .add(...ixs);
@@ -1161,9 +1222,9 @@ class ClearingHouse {
1161
1222
  const userStatsPublicKey = (0, pda_1.getUserStatsAccountPublicKey)(this.program.programId, userAccount.authority);
1162
1223
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1163
1224
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
1164
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1225
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1165
1226
  writableMarketIndex: marketIndex,
1166
- userAccount,
1227
+ counterPartyUserAccount: userAccount,
1167
1228
  });
1168
1229
  return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
1169
1230
  accounts: {
@@ -1183,8 +1244,8 @@ class ClearingHouse {
1183
1244
  }
1184
1245
  async getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer) {
1185
1246
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1186
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1187
- userAccount,
1247
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1248
+ counterPartyUserAccount: userAccount,
1188
1249
  writableBankIndexes: [liabilityBankIndex, assetBankIndex],
1189
1250
  });
1190
1251
  return await this.program.instruction.liquidateBorrow(assetBankIndex, liabilityBankIndex, maxLiabilityTransfer, {
@@ -1203,8 +1264,8 @@ class ClearingHouse {
1203
1264
  }
1204
1265
  async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer) {
1205
1266
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1206
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1207
- userAccount,
1267
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1268
+ counterPartyUserAccount: userAccount,
1208
1269
  writableMarketIndex: perpMarketIndex,
1209
1270
  writableBankIndexes: [liabilityBankIndex],
1210
1271
  });
@@ -1224,8 +1285,8 @@ class ClearingHouse {
1224
1285
  }
1225
1286
  async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer) {
1226
1287
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1227
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1228
- userAccount,
1288
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1289
+ counterPartyUserAccount: userAccount,
1229
1290
  writableMarketIndex: perpMarketIndex,
1230
1291
  writableBankIndexes: [assetBankIndex],
1231
1292
  });
@@ -1245,9 +1306,9 @@ class ClearingHouse {
1245
1306
  }
1246
1307
  async getResolvePerpBankruptcyIx(userAccountPublicKey, userAccount, marketIndex) {
1247
1308
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1248
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1309
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1249
1310
  writableMarketIndex: marketIndex,
1250
- userAccount,
1311
+ counterPartyUserAccount: userAccount,
1251
1312
  });
1252
1313
  return await this.program.instruction.resolvePerpBankruptcy(marketIndex, {
1253
1314
  accounts: {
@@ -1265,9 +1326,9 @@ class ClearingHouse {
1265
1326
  }
1266
1327
  async getResolveBorrowBankruptcyIx(userAccountPublicKey, userAccount, bankIndex) {
1267
1328
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1268
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1329
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1269
1330
  writableBankIndexes: [bankIndex],
1270
- userAccount,
1331
+ counterPartyUserAccount: userAccount,
1271
1332
  });
1272
1333
  return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
1273
1334
  accounts: {
@@ -1279,12 +1340,12 @@ class ClearingHouse {
1279
1340
  remainingAccounts: remainingAccounts,
1280
1341
  });
1281
1342
  }
1282
- getRemainingAccountsForLiquidation(params) {
1283
- const liquidateeUserAccount = params.userAccount;
1343
+ getRemainingAccountsWithCounterparty(params) {
1344
+ const counterPartyUserAccount = params.counterPartyUserAccount;
1284
1345
  const oracleAccountMap = new Map();
1285
1346
  const bankAccountMap = new Map();
1286
1347
  const marketAccountMap = new Map();
1287
- for (const bankBalance of liquidateeUserAccount.bankBalances) {
1348
+ for (const bankBalance of counterPartyUserAccount.bankBalances) {
1288
1349
  if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
1289
1350
  const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1290
1351
  bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
@@ -1301,7 +1362,7 @@ class ClearingHouse {
1301
1362
  }
1302
1363
  }
1303
1364
  }
1304
- for (const position of liquidateeUserAccount.positions) {
1365
+ for (const position of counterPartyUserAccount.positions) {
1305
1366
  if (!(0, position_1.positionIsAvailable)(position)) {
1306
1367
  const market = this.getMarketAccount(position.marketIndex);
1307
1368
  marketAccountMap.set(position.marketIndex.toNumber(), {
@@ -37,6 +37,7 @@ export declare class ClearingHouseUser {
37
37
  */
38
38
  getUserPosition(marketIndex: BN): UserPosition | undefined;
39
39
  getEmptyPosition(marketIndex: BN): UserPosition;
40
+ getClonedPosition(position: UserPosition): UserPosition;
40
41
  /**
41
42
  * @param orderId
42
43
  * @returns Order
@@ -53,7 +54,7 @@ export declare class ClearingHouseUser {
53
54
  * calculates the market position if the lp position was settled
54
55
  * @returns : userPosition
55
56
  */
56
- getSettledLPPosition(marketIndex: BN): [UserPosition, BN];
57
+ getSettledLPPosition(marketIndex: BN): [UserPosition, BN, BN];
57
58
  /**
58
59
  * calculates Buying Power = FC * MAX_LEVERAGE
59
60
  * @returns : Precision QUOTE_PRECISION
@@ -64,6 +65,13 @@ export declare class ClearingHouseUser {
64
65
  * @returns : Precision QUOTE_PRECISION
65
66
  */
66
67
  getFreeCollateral(): BN;
68
+ /**
69
+ * @returns The margin requirement of a certain type (Initial or Maintenance) in USDC. : QUOTE_PRECISION
70
+ */
71
+ getMarginRequirement(type: MarginCategory): BN;
72
+ /**
73
+ * @returns The initial margin requirement in USDC. : QUOTE_PRECISION
74
+ */
67
75
  getInitialMarginRequirement(): BN;
68
76
  /**
69
77
  * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
@@ -78,6 +78,10 @@ class ClearingHouseUser {
78
78
  lastNetQuoteAssetAmountPerLp: numericConstants_1.ZERO,
79
79
  };
80
80
  }
81
+ getClonedPosition(position) {
82
+ const clonedPosition = Object.assign({}, position);
83
+ return clonedPosition;
84
+ }
81
85
  /**
82
86
  * @param orderId
83
87
  * @returns Order
@@ -104,7 +108,8 @@ class ClearingHouseUser {
104
108
  * @returns : userPosition
105
109
  */
106
110
  getSettledLPPosition(marketIndex) {
107
- const position = this.getUserPosition(marketIndex);
111
+ const _position = this.getUserPosition(marketIndex);
112
+ const position = this.getClonedPosition(_position);
108
113
  const market = this.clearingHouse.getMarketAccount(position.marketIndex);
109
114
  const nShares = position.lpShares;
110
115
  const deltaBaa = market.amm.marketPositionPerLp.baseAssetAmount
@@ -180,7 +185,7 @@ class ClearingHouseUser {
180
185
  else {
181
186
  position.lastCumulativeFundingRate = numericConstants_1.ZERO;
182
187
  }
183
- return [position, pnl];
188
+ return [position, remainderBaa, pnl];
184
189
  }
185
190
  /**
186
191
  * calculates Buying Power = FC * MAX_LEVERAGE
@@ -201,37 +206,69 @@ class ClearingHouseUser {
201
206
  const freeCollateral = totalCollateral.sub(initialMarginRequirement);
202
207
  return freeCollateral.gte(numericConstants_1.ZERO) ? freeCollateral : numericConstants_1.ZERO;
203
208
  }
204
- getInitialMarginRequirement() {
205
- const postionMarginRequirement = this.getUserAccount().positions.reduce((marginRequirement, marketPosition) => {
206
- const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
207
- const worstCaseBaseAssetAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(marketPosition);
208
- const worstCaseAssetValue = worstCaseBaseAssetAmount
209
- .abs()
210
- .mul(this.getOracleDataForMarket(market.marketIndex).price)
211
- .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
212
- const marketMarginRatio = new _1.BN((0, _1.calculateMarketMarginRatio)(market, worstCaseBaseAssetAmount.abs(), 'Initial'));
213
- return marginRequirement.add(worstCaseAssetValue.mul(marketMarginRatio).div(numericConstants_1.MARGIN_PRECISION));
214
- }, numericConstants_1.ZERO);
215
- const bankMarginRequirement = this.getBankLiabilityValue(undefined, 'Initial');
216
- return bankMarginRequirement.add(postionMarginRequirement);
217
- }
218
209
  /**
219
- * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
210
+ * @returns The margin requirement of a certain type (Initial or Maintenance) in USDC. : QUOTE_PRECISION
220
211
  */
221
- getMaintenanceMarginRequirement() {
212
+ getMarginRequirement(type) {
222
213
  return this.getUserAccount()
223
214
  .positions.reduce((marginRequirement, marketPosition) => {
224
215
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
216
+ if (marketPosition.lpShares.gt(numericConstants_1.ZERO)) {
217
+ // is an lp
218
+ // clone so we dont mutate the position
219
+ marketPosition = this.getClonedPosition(marketPosition);
220
+ // settle position
221
+ const [settledPosition, dustBaa, _] = this.getSettledLPPosition(market.marketIndex);
222
+ marketPosition.baseAssetAmount =
223
+ settledPosition.baseAssetAmount.add(dustBaa);
224
+ marketPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
225
+ // open orders
226
+ let openAsks;
227
+ if (market.amm.maxBaseAssetReserve > market.amm.baseAssetReserve) {
228
+ openAsks = market.amm.maxBaseAssetReserve
229
+ .sub(market.amm.baseAssetReserve)
230
+ .mul(marketPosition.lpShares)
231
+ .div(market.amm.sqrtK)
232
+ .mul(new _1.BN(-1));
233
+ }
234
+ else {
235
+ openAsks = numericConstants_1.ZERO;
236
+ }
237
+ let openBids;
238
+ if (market.amm.minBaseAssetReserve < market.amm.baseAssetReserve) {
239
+ openBids = market.amm.baseAssetReserve
240
+ .sub(market.amm.minBaseAssetReserve)
241
+ .mul(marketPosition.lpShares)
242
+ .div(market.amm.sqrtK);
243
+ }
244
+ else {
245
+ openBids = numericConstants_1.ZERO;
246
+ }
247
+ marketPosition.openAsks = marketPosition.openAsks.add(openAsks);
248
+ marketPosition.openBids = marketPosition.openBids.add(openBids);
249
+ }
225
250
  const worstCaseBaseAssetAmount = (0, margin_1.calculateWorstCaseBaseAssetAmount)(marketPosition);
226
251
  const worstCaseAssetValue = worstCaseBaseAssetAmount
227
252
  .abs()
228
253
  .mul(this.getOracleDataForMarket(market.marketIndex).price)
229
254
  .div(numericConstants_1.AMM_TO_QUOTE_PRECISION_RATIO.mul(numericConstants_1.MARK_PRICE_PRECISION));
230
255
  return marginRequirement.add(worstCaseAssetValue
231
- .mul(new _1.BN((0, _1.calculateMarketMarginRatio)(market, worstCaseBaseAssetAmount.abs(), 'Maintenance')))
256
+ .mul(new _1.BN((0, _1.calculateMarketMarginRatio)(market, worstCaseBaseAssetAmount.abs(), type)))
232
257
  .div(numericConstants_1.MARGIN_PRECISION));
233
258
  }, numericConstants_1.ZERO)
234
- .add(this.getBankLiabilityValue(undefined, 'Maintenance'));
259
+ .add(this.getBankLiabilityValue(undefined, type));
260
+ }
261
+ /**
262
+ * @returns The initial margin requirement in USDC. : QUOTE_PRECISION
263
+ */
264
+ getInitialMarginRequirement() {
265
+ return this.getMarginRequirement('Initial');
266
+ }
267
+ /**
268
+ * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
269
+ */
270
+ getMaintenanceMarginRequirement() {
271
+ return this.getMarginRequirement('Maintenance');
235
272
  }
236
273
  /**
237
274
  * calculates unrealized position price pnl
@@ -240,17 +277,17 @@ class ClearingHouseUser {
240
277
  getUnrealizedPNL(withFunding, marketIndex, withWeightMarginCategory) {
241
278
  return this.getUserAccount()
242
279
  .positions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
243
- .reduce((pnl, marketPosition) => {
280
+ .reduce((unrealizedPnl, marketPosition) => {
244
281
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
245
- let pnl0 = (0, _1.calculatePositionPNL)(market, marketPosition, withFunding, this.getOracleDataForMarket(market.marketIndex));
282
+ let positionUnrealizedPnl = (0, _1.calculatePositionPNL)(market, marketPosition, withFunding, this.getOracleDataForMarket(market.marketIndex));
246
283
  if (withWeightMarginCategory !== undefined) {
247
- if (pnl0.gt(numericConstants_1.ZERO)) {
248
- pnl0 = pnl0
249
- .mul((0, _1.calculateUnsettledAssetWeight)(market, pnl0, withWeightMarginCategory))
284
+ if (positionUnrealizedPnl.gt(numericConstants_1.ZERO)) {
285
+ positionUnrealizedPnl = positionUnrealizedPnl
286
+ .mul((0, _1.calculateUnrealizedAssetWeight)(market, positionUnrealizedPnl, withWeightMarginCategory))
250
287
  .div(new _1.BN(numericConstants_1.BANK_WEIGHT_PRECISION));
251
288
  }
252
289
  }
253
- return pnl.add(pnl0);
290
+ return unrealizedPnl.add(positionUnrealizedPnl);
254
291
  }, numericConstants_1.ZERO);
255
292
  }
256
293
  /**
@@ -317,25 +354,7 @@ class ClearingHouseUser {
317
354
  * @returns : Precision QUOTE_PRECISION
318
355
  */
319
356
  getTotalCollateral(marginCategory = 'Initial') {
320
- return this.getUserAccount()
321
- .bankBalances.reduce((totalAssetValue, bankBalance) => {
322
- if (bankBalance.balance.eq(numericConstants_1.ZERO) ||
323
- (0, types_1.isVariant)(bankBalance.balanceType, 'borrow')) {
324
- return totalAssetValue;
325
- }
326
- // Todo this needs to account for whether it's based on initial or maintenance requirements
327
- const bankAccount = this.clearingHouse.getBankAccount(bankBalance.bankIndex);
328
- const tokenAmount = (0, bankBalance_1.getTokenAmount)(bankBalance.balance, bankAccount, bankBalance.balanceType);
329
- const weight = (0, bankBalance_1.calculateAssetWeight)(tokenAmount, bankAccount, marginCategory);
330
- return totalAssetValue.add(tokenAmount
331
- .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
332
- .mul(weight)
333
- .div(numericConstants_1.BANK_WEIGHT_PRECISION)
334
- .div(numericConstants_1.MARK_PRICE_PRECISION)
335
- // Adjust for decimals of bank account
336
- .div(new _1.BN(10).pow(new _1.BN(bankAccount.decimals).sub(numericConstants_1.BANK_BALANCE_PRECISION_EXP))));
337
- }, numericConstants_1.ZERO)
338
- .add(this.getUnrealizedPNL(true, undefined, marginCategory));
357
+ return this.getBankAssetValue(undefined, marginCategory).add(this.getUnrealizedPNL(true, undefined, marginCategory));
339
358
  }
340
359
  /**
341
360
  * calculates sum of position value across all positions in margin system
@@ -2,7 +2,7 @@ import { ClearingHouse } from './clearingHouse';
2
2
  import { PublicKey } from '@solana/web3.js';
3
3
  import { DataAndSlot, UserStatsAccountSubscriber } from './accounts/types';
4
4
  import { ClearingHouseUserStatsConfig } from './clearingHouseUserStatsConfig';
5
- import { UserStatsAccount } from './types';
5
+ import { ReferrerInfo, UserStatsAccount } from './types';
6
6
  export declare class ClearingHouseUserStats {
7
7
  clearingHouse: ClearingHouse;
8
8
  userStatsAccountPublicKey: PublicKey;
@@ -14,4 +14,5 @@ export declare class ClearingHouseUserStats {
14
14
  unsubscribe(): Promise<void>;
15
15
  getAccountAndSlot(): DataAndSlot<UserStatsAccount>;
16
16
  getAccount(): UserStatsAccount;
17
+ getReferrerInfo(): ReferrerInfo | undefined;
17
18
  }
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ClearingHouseUserStats = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
4
5
  const pollingUserStatsAccountSubscriber_1 = require("./accounts/pollingUserStatsAccountSubscriber");
5
6
  const webSocketUserStatsAccountSubsriber_1 = require("./accounts/webSocketUserStatsAccountSubsriber");
7
+ const pda_1 = require("./addresses/pda");
6
8
  class ClearingHouseUserStats {
7
9
  constructor(config) {
8
10
  var _a;
@@ -32,5 +34,16 @@ class ClearingHouseUserStats {
32
34
  getAccount() {
33
35
  return this.accountSubscriber.getUserStatsAccountAndSlot().data;
34
36
  }
37
+ getReferrerInfo() {
38
+ if (this.getAccount().referrer.equals(web3_js_1.PublicKey.default)) {
39
+ return undefined;
40
+ }
41
+ else {
42
+ return {
43
+ referrer: (0, pda_1.getUserAccountPublicKeySync)(this.clearingHouse.program.programId, this.getAccount().referrer, 0),
44
+ referrerStats: (0, pda_1.getUserStatsAccountPublicKey)(this.clearingHouse.program.programId, this.getAccount().referrer),
45
+ };
46
+ }
47
+ }
35
48
  }
36
49
  exports.ClearingHouseUserStats = ClearingHouseUserStats;
package/lib/config.js CHANGED
@@ -7,7 +7,7 @@ exports.configs = {
7
7
  devnet: {
8
8
  ENV: 'devnet',
9
9
  PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
10
- CLEARING_HOUSE_PROGRAM_ID: 'D9bW92Maa1yDigJqvabRgr5S5VybPNDB5xxSpQD6mkkV',
10
+ CLEARING_HOUSE_PROGRAM_ID: '65sz7dRiWDRPZjiRxcTxPM7AE6VK4Nag9HEK6oBJXhJn',
11
11
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
12
12
  MARKETS: markets_1.DevnetMarkets,
13
13
  BANKS: banks_1.DevnetBanks,
@@ -1,5 +1,5 @@
1
1
  import { Commitment, TransactionSignature } from '@solana/web3.js';
2
- import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, OrderRecord, SettlePnlRecord } from '../index';
2
+ import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, NewUserRecord, OrderRecord, SettlePnlRecord } from '../index';
3
3
  export declare type EventSubscriptionOptions = {
4
4
  eventTypes?: EventType[];
5
5
  maxEventsPerType?: number;
@@ -28,6 +28,7 @@ export declare type EventMap = {
28
28
  FundingRateRecord: Event<FundingRateRecord>;
29
29
  OrderRecord: Event<OrderRecord>;
30
30
  SettlePnlRecord: Event<SettlePnlRecord>;
31
+ NewUserRecord: Event<NewUserRecord>;
31
32
  };
32
33
  export declare type EventType = keyof EventMap;
33
34
  export interface EventSubscriberEvents {