@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
@@ -15,6 +15,7 @@ import {
15
15
  OptionalOrderParams,
16
16
  DefaultOrderParams,
17
17
  OrderType,
18
+ ReferrerInfo,
18
19
  } from './types';
19
20
  import * as anchor from '@project-serum/anchor';
20
21
  import clearingHouseIDL from './idl/clearing_house.json';
@@ -51,7 +52,11 @@ import {
51
52
  } from './accounts/types';
52
53
  import { TxSender } from './tx/types';
53
54
  import { wrapInTx } from './tx/utils';
54
- import { QUOTE_ASSET_BANK_INDEX, ZERO } from './constants/numericConstants';
55
+ import {
56
+ ONE,
57
+ QUOTE_ASSET_BANK_INDEX,
58
+ ZERO,
59
+ } from './constants/numericConstants';
55
60
  import { findDirectionToClose, positionIsAvailable } from './math/position';
56
61
  import { getTokenAmount } from './math/bankBalance';
57
62
  import { DEFAULT_USER_NAME, encodeName } from './userName';
@@ -219,11 +224,13 @@ export class ClearingHouse {
219
224
  * Forces the accountSubscriber to fetch account updates from rpc
220
225
  */
221
226
  public async fetchAccounts(): Promise<void> {
222
- await Promise.all(
223
- [...this.users.values()]
224
- .map((user) => user.fetchAccounts())
225
- .concat(this.accountSubscriber.fetch())
226
- );
227
+ const promises = [...this.users.values()]
228
+ .map((user) => user.fetchAccounts())
229
+ .concat(this.accountSubscriber.fetch());
230
+ if (this.userStats) {
231
+ promises.concat(this.userStats.fetchAccounts());
232
+ }
233
+ await Promise.all(promises);
227
234
  }
228
235
 
229
236
  public async unsubscribe(): Promise<void> {
@@ -341,10 +348,11 @@ export class ClearingHouse {
341
348
 
342
349
  public async initializeUserAccount(
343
350
  userId = 0,
344
- name = DEFAULT_USER_NAME
351
+ name = DEFAULT_USER_NAME,
352
+ referrerInfo?: ReferrerInfo
345
353
  ): Promise<[TransactionSignature, PublicKey]> {
346
354
  const [userAccountPublicKey, initializeUserAccountIx] =
347
- await this.getInitializeUserInstructions(userId, name);
355
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
348
356
 
349
357
  const tx = new Transaction();
350
358
  if (userId === 0) {
@@ -358,7 +366,8 @@ export class ClearingHouse {
358
366
 
359
367
  async getInitializeUserInstructions(
360
368
  userId = 0,
361
- name = DEFAULT_USER_NAME
369
+ name = DEFAULT_USER_NAME,
370
+ referrerInfo?: ReferrerInfo
362
371
  ): Promise<[PublicKey, TransactionInstruction]> {
363
372
  const userAccountPublicKey = await getUserAccountPublicKey(
364
373
  this.program.programId,
@@ -366,6 +375,20 @@ export class ClearingHouse {
366
375
  userId
367
376
  );
368
377
 
378
+ const remainingAccounts = new Array<AccountMeta>();
379
+ if (referrerInfo !== undefined) {
380
+ remainingAccounts.push({
381
+ pubkey: referrerInfo.referrer,
382
+ isWritable: true,
383
+ isSigner: false,
384
+ });
385
+ remainingAccounts.push({
386
+ pubkey: referrerInfo.referrerStats,
387
+ isWritable: true,
388
+ isSigner: false,
389
+ });
390
+ }
391
+
369
392
  const nameBuffer = encodeName(name);
370
393
  const initializeUserAccountIx =
371
394
  await this.program.instruction.initializeUser(userId, nameBuffer, {
@@ -378,6 +401,7 @@ export class ClearingHouse {
378
401
  systemProgram: anchor.web3.SystemProgram.programId,
379
402
  state: await this.getStatePublicKey(),
380
403
  },
404
+ remainingAccounts,
381
405
  });
382
406
 
383
407
  return [userAccountPublicKey, initializeUserAccountIx];
@@ -711,6 +735,7 @@ export class ClearingHouse {
711
735
  bank: bank.pubkey,
712
736
  bankVault: bank.vault,
713
737
  user: userAccountPublicKey,
738
+ userStats: this.getUserStatsAccountPublicKey(),
714
739
  userTokenAccount: userTokenAccount,
715
740
  authority: this.wallet.publicKey,
716
741
  tokenProgram: TOKEN_PROGRAM_ID,
@@ -842,10 +867,11 @@ export class ClearingHouse {
842
867
  bankIndex = new BN(0),
843
868
  userId = 0,
844
869
  name = DEFAULT_USER_NAME,
845
- fromUserId?: number
870
+ fromUserId?: number,
871
+ referrerInfo?: ReferrerInfo
846
872
  ): Promise<[TransactionSignature, PublicKey]> {
847
873
  const [userAccountPublicKey, initializeUserAccountIx] =
848
- await this.getInitializeUserInstructions(userId, name);
874
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
849
875
 
850
876
  const additionalSigners: Array<Signer> = [];
851
877
 
@@ -920,7 +946,8 @@ export class ClearingHouse {
920
946
  name = DEFAULT_USER_NAME,
921
947
  bankIndex: BN,
922
948
  tokenFaucet: TokenFaucet,
923
- amount: BN
949
+ amount: BN,
950
+ referrerInfo?: ReferrerInfo
924
951
  ): Promise<[TransactionSignature, PublicKey]> {
925
952
  const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] =
926
953
  await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(
@@ -929,7 +956,7 @@ export class ClearingHouse {
929
956
  );
930
957
 
931
958
  const [userAccountPublicKey, initializeUserAccountIx] =
932
- await this.getInitializeUserInstructions(userId, name);
959
+ await this.getInitializeUserInstructions(userId, name, referrerInfo);
933
960
 
934
961
  const depositCollateralIx = await this.getDepositInstruction(
935
962
  amount,
@@ -1038,6 +1065,7 @@ export class ClearingHouse {
1038
1065
  bankVault: bank.vault,
1039
1066
  bankVaultAuthority: bank.vaultAuthority,
1040
1067
  user: userAccountPublicKey,
1068
+ userStats: this.getUserStatsAccountPublicKey(),
1041
1069
  userTokenAccount: userTokenAccount,
1042
1070
  authority: this.wallet.publicKey,
1043
1071
  tokenProgram: TOKEN_PROGRAM_ID,
@@ -1089,6 +1117,7 @@ export class ClearingHouse {
1089
1117
  authority: this.wallet.publicKey,
1090
1118
  fromUser,
1091
1119
  toUser,
1120
+ userStats: this.getUserStatsAccountPublicKey(),
1092
1121
  state: await this.getStatePublicKey(),
1093
1122
  },
1094
1123
  remainingAccounts,
@@ -1401,11 +1430,18 @@ export class ClearingHouse {
1401
1430
  userAccountPublicKey: PublicKey,
1402
1431
  user: UserAccount,
1403
1432
  order?: Order,
1404
- makerInfo?: MakerInfo
1433
+ makerInfo?: MakerInfo,
1434
+ referrerInfo?: ReferrerInfo
1405
1435
  ): Promise<TransactionSignature> {
1406
1436
  const { txSig } = await this.txSender.send(
1407
1437
  wrapInTx(
1408
- await this.getFillOrderIx(userAccountPublicKey, user, order, makerInfo)
1438
+ await this.getFillOrderIx(
1439
+ userAccountPublicKey,
1440
+ user,
1441
+ order,
1442
+ makerInfo,
1443
+ referrerInfo
1444
+ )
1409
1445
  ),
1410
1446
  [],
1411
1447
  this.opts
@@ -1417,7 +1453,8 @@ export class ClearingHouse {
1417
1453
  userAccountPublicKey: PublicKey,
1418
1454
  userAccount: UserAccount,
1419
1455
  order: Order,
1420
- makerInfo?: MakerInfo
1456
+ makerInfo?: MakerInfo,
1457
+ referrerInfo?: ReferrerInfo
1421
1458
  ): Promise<TransactionInstruction> {
1422
1459
  const userStatsPublicKey = getUserStatsAccountPublicKey(
1423
1460
  this.program.programId,
@@ -1427,7 +1464,11 @@ export class ClearingHouse {
1427
1464
  const fillerPublicKey = await this.getUserAccountPublicKey();
1428
1465
  const fillerStatsPublicKey = this.getUserStatsAccountPublicKey();
1429
1466
 
1430
- const marketIndex = order.marketIndex;
1467
+ const marketIndex = order
1468
+ ? order.marketIndex
1469
+ : userAccount.orders.find((order) =>
1470
+ order.orderId.eq(userAccount.nextOrderId.sub(ONE))
1471
+ ).marketIndex;
1431
1472
  const marketAccount = this.getMarketAccount(marketIndex);
1432
1473
 
1433
1474
  const oracleAccountMap = new Map<string, AccountMeta>();
@@ -1502,6 +1543,19 @@ export class ClearingHouse {
1502
1543
  });
1503
1544
  }
1504
1545
 
1546
+ if (referrerInfo) {
1547
+ remainingAccounts.push({
1548
+ pubkey: referrerInfo.referrer,
1549
+ isWritable: true,
1550
+ isSigner: false,
1551
+ });
1552
+ remainingAccounts.push({
1553
+ pubkey: referrerInfo.referrerStats,
1554
+ isWritable: true,
1555
+ isSigner: false,
1556
+ });
1557
+ }
1558
+
1505
1559
  const orderId = order.orderId;
1506
1560
  const makerOrderId = makerInfo ? makerInfo.order.orderId : null;
1507
1561
 
@@ -1614,10 +1668,13 @@ export class ClearingHouse {
1614
1668
 
1615
1669
  public async placeAndTake(
1616
1670
  orderParams: OptionalOrderParams,
1617
- makerInfo?: MakerInfo
1671
+ makerInfo?: MakerInfo,
1672
+ referrerInfo?: ReferrerInfo
1618
1673
  ): Promise<TransactionSignature> {
1619
1674
  const { txSig, slot } = await this.txSender.send(
1620
- wrapInTx(await this.getPlaceAndTakeIx(orderParams, makerInfo)),
1675
+ wrapInTx(
1676
+ await this.getPlaceAndTakeIx(orderParams, makerInfo, referrerInfo)
1677
+ ),
1621
1678
  [],
1622
1679
  this.opts
1623
1680
  );
@@ -1627,7 +1684,8 @@ export class ClearingHouse {
1627
1684
 
1628
1685
  public async getPlaceAndTakeIx(
1629
1686
  orderParams: OptionalOrderParams,
1630
- makerInfo?: MakerInfo
1687
+ makerInfo?: MakerInfo,
1688
+ referrerInfo?: ReferrerInfo
1631
1689
  ): Promise<TransactionInstruction> {
1632
1690
  orderParams = this.getOrderParams(orderParams);
1633
1691
  const userStatsPublicKey = await this.getUserStatsAccountPublicKey();
@@ -1653,6 +1711,19 @@ export class ClearingHouse {
1653
1711
  });
1654
1712
  }
1655
1713
 
1714
+ if (referrerInfo) {
1715
+ remainingAccounts.push({
1716
+ pubkey: referrerInfo.referrer,
1717
+ isWritable: true,
1718
+ isSigner: false,
1719
+ });
1720
+ remainingAccounts.push({
1721
+ pubkey: referrerInfo.referrerStats,
1722
+ isWritable: true,
1723
+ isSigner: false,
1724
+ });
1725
+ }
1726
+
1656
1727
  return await this.program.instruction.placeAndTake(
1657
1728
  orderParams,
1658
1729
  makerOrderId,
@@ -1670,10 +1741,13 @@ export class ClearingHouse {
1670
1741
 
1671
1742
  public async placeAndMake(
1672
1743
  orderParams: OptionalOrderParams,
1673
- takerInfo: TakerInfo
1744
+ takerInfo: TakerInfo,
1745
+ referrerInfo?: ReferrerInfo
1674
1746
  ): Promise<TransactionSignature> {
1675
1747
  const { txSig, slot } = await this.txSender.send(
1676
- wrapInTx(await this.getPlaceAndMakeIx(orderParams, takerInfo)),
1748
+ wrapInTx(
1749
+ await this.getPlaceAndMakeIx(orderParams, takerInfo, referrerInfo)
1750
+ ),
1677
1751
  [],
1678
1752
  this.opts
1679
1753
  );
@@ -1685,16 +1759,32 @@ export class ClearingHouse {
1685
1759
 
1686
1760
  public async getPlaceAndMakeIx(
1687
1761
  orderParams: OptionalOrderParams,
1688
- takerInfo: TakerInfo
1762
+ takerInfo: TakerInfo,
1763
+ referrerInfo?: ReferrerInfo
1689
1764
  ): Promise<TransactionInstruction> {
1690
1765
  orderParams = this.getOrderParams(orderParams);
1691
1766
  const userStatsPublicKey = this.getUserStatsAccountPublicKey();
1692
1767
  const userAccountPublicKey = await this.getUserAccountPublicKey();
1693
1768
 
1694
- const remainingAccounts = this.getRemainingAccounts({
1769
+ // todo merge this with getRemainingAccounts
1770
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1771
+ counterPartyUserAccount: takerInfo.takerUserAccount,
1695
1772
  writableMarketIndex: orderParams.marketIndex,
1696
1773
  });
1697
1774
 
1775
+ if (referrerInfo) {
1776
+ remainingAccounts.push({
1777
+ pubkey: referrerInfo.referrer,
1778
+ isWritable: true,
1779
+ isSigner: false,
1780
+ });
1781
+ remainingAccounts.push({
1782
+ pubkey: referrerInfo.referrerStats,
1783
+ isWritable: true,
1784
+ isSigner: false,
1785
+ });
1786
+ }
1787
+
1698
1788
  const takerOrderId = takerInfo!.order!.orderId;
1699
1789
  return await this.program.instruction.placeAndMake(
1700
1790
  orderParams,
@@ -1758,7 +1848,7 @@ export class ClearingHouse {
1758
1848
  const tx = new Transaction()
1759
1849
  .add(
1760
1850
  ComputeBudgetProgram.requestUnits({
1761
- units: 1_200_000,
1851
+ units: 1_000_000,
1762
1852
  additionalFee: 0,
1763
1853
  })
1764
1854
  )
@@ -1899,9 +1989,9 @@ export class ClearingHouse {
1899
1989
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1900
1990
  const liquidatorStatsPublicKey = this.getUserStatsAccountPublicKey();
1901
1991
 
1902
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1992
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
1903
1993
  writableMarketIndex: marketIndex,
1904
- userAccount,
1994
+ counterPartyUserAccount: userAccount,
1905
1995
  });
1906
1996
 
1907
1997
  return await this.program.instruction.liquidatePerp(
@@ -1953,8 +2043,8 @@ export class ClearingHouse {
1953
2043
  ): Promise<TransactionInstruction> {
1954
2044
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
1955
2045
 
1956
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
1957
- userAccount,
2046
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2047
+ counterPartyUserAccount: userAccount,
1958
2048
  writableBankIndexes: [liabilityBankIndex, assetBankIndex],
1959
2049
  });
1960
2050
 
@@ -2006,8 +2096,8 @@ export class ClearingHouse {
2006
2096
  ): Promise<TransactionInstruction> {
2007
2097
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2008
2098
 
2009
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
2010
- userAccount,
2099
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2100
+ counterPartyUserAccount: userAccount,
2011
2101
  writableMarketIndex: perpMarketIndex,
2012
2102
  writableBankIndexes: [liabilityBankIndex],
2013
2103
  });
@@ -2060,8 +2150,8 @@ export class ClearingHouse {
2060
2150
  ): Promise<TransactionInstruction> {
2061
2151
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2062
2152
 
2063
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
2064
- userAccount,
2153
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2154
+ counterPartyUserAccount: userAccount,
2065
2155
  writableMarketIndex: perpMarketIndex,
2066
2156
  writableBankIndexes: [assetBankIndex],
2067
2157
  });
@@ -2108,9 +2198,9 @@ export class ClearingHouse {
2108
2198
  ): Promise<TransactionInstruction> {
2109
2199
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2110
2200
 
2111
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
2201
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2112
2202
  writableMarketIndex: marketIndex,
2113
- userAccount,
2203
+ counterPartyUserAccount: userAccount,
2114
2204
  });
2115
2205
 
2116
2206
  return await this.program.instruction.resolvePerpBankruptcy(marketIndex, {
@@ -2150,9 +2240,9 @@ export class ClearingHouse {
2150
2240
  ): Promise<TransactionInstruction> {
2151
2241
  const liquidatorPublicKey = await this.getUserAccountPublicKey();
2152
2242
 
2153
- const remainingAccounts = this.getRemainingAccountsForLiquidation({
2243
+ const remainingAccounts = this.getRemainingAccountsWithCounterparty({
2154
2244
  writableBankIndexes: [bankIndex],
2155
- userAccount,
2245
+ counterPartyUserAccount: userAccount,
2156
2246
  });
2157
2247
 
2158
2248
  return await this.program.instruction.resolveBorrowBankruptcy(bankIndex, {
@@ -2166,17 +2256,17 @@ export class ClearingHouse {
2166
2256
  });
2167
2257
  }
2168
2258
 
2169
- getRemainingAccountsForLiquidation(params: {
2170
- userAccount: UserAccount;
2259
+ getRemainingAccountsWithCounterparty(params: {
2260
+ counterPartyUserAccount: UserAccount;
2171
2261
  writableMarketIndex?: BN;
2172
2262
  writableBankIndexes?: BN[];
2173
2263
  }): AccountMeta[] {
2174
- const liquidateeUserAccount = params.userAccount;
2264
+ const counterPartyUserAccount = params.counterPartyUserAccount;
2175
2265
 
2176
2266
  const oracleAccountMap = new Map<string, AccountMeta>();
2177
2267
  const bankAccountMap = new Map<number, AccountMeta>();
2178
2268
  const marketAccountMap = new Map<number, AccountMeta>();
2179
- for (const bankBalance of liquidateeUserAccount.bankBalances) {
2269
+ for (const bankBalance of counterPartyUserAccount.bankBalances) {
2180
2270
  if (!bankBalance.balance.eq(ZERO)) {
2181
2271
  const bankAccount = this.getBankAccount(bankBalance.bankIndex);
2182
2272
  bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
@@ -2194,7 +2284,7 @@ export class ClearingHouse {
2194
2284
  }
2195
2285
  }
2196
2286
  }
2197
- for (const position of liquidateeUserAccount.positions) {
2287
+ for (const position of counterPartyUserAccount.positions) {
2198
2288
  if (!positionIsAvailable(position)) {
2199
2289
  const market = this.getMarketAccount(position.marketIndex);
2200
2290
  marketAccountMap.set(position.marketIndex.toNumber(), {
@@ -33,7 +33,7 @@ import {
33
33
  calculateBaseAssetValue,
34
34
  calculatePositionFundingPNL,
35
35
  calculatePositionPNL,
36
- calculateUnsettledAssetWeight,
36
+ calculateUnrealizedAssetWeight,
37
37
  calculateMarketMarginRatio,
38
38
  PositionDirection,
39
39
  calculateTradeSlippage,
@@ -144,6 +144,11 @@ export class ClearingHouseUser {
144
144
  };
145
145
  }
146
146
 
147
+ public getClonedPosition(position: UserPosition): UserPosition {
148
+ const clonedPosition = Object.assign({}, position);
149
+ return clonedPosition;
150
+ }
151
+
147
152
  /**
148
153
  * @param orderId
149
154
  * @returns Order
@@ -180,8 +185,10 @@ export class ClearingHouseUser {
180
185
  * calculates the market position if the lp position was settled
181
186
  * @returns : userPosition
182
187
  */
183
- public getSettledLPPosition(marketIndex: BN): [UserPosition, BN] {
184
- const position = this.getUserPosition(marketIndex);
188
+ public getSettledLPPosition(marketIndex: BN): [UserPosition, BN, BN] {
189
+ const _position = this.getUserPosition(marketIndex);
190
+ const position = this.getClonedPosition(_position);
191
+
185
192
  const market = this.clearingHouse.getMarketAccount(position.marketIndex);
186
193
  const nShares = position.lpShares;
187
194
 
@@ -265,7 +272,7 @@ export class ClearingHouseUser {
265
272
  position.lastCumulativeFundingRate = ZERO;
266
273
  }
267
274
 
268
- return [position, pnl];
275
+ return [position, remainderBaa, pnl];
269
276
  }
270
277
 
271
278
  /**
@@ -289,51 +296,55 @@ export class ClearingHouseUser {
289
296
  return freeCollateral.gte(ZERO) ? freeCollateral : ZERO;
290
297
  }
291
298
 
292
- public getInitialMarginRequirement(): BN {
293
- const postionMarginRequirement = this.getUserAccount().positions.reduce(
294
- (marginRequirement, marketPosition) => {
299
+ /**
300
+ * @returns The margin requirement of a certain type (Initial or Maintenance) in USDC. : QUOTE_PRECISION
301
+ */
302
+ public getMarginRequirement(type: MarginCategory): BN {
303
+ return this.getUserAccount()
304
+ .positions.reduce((marginRequirement, marketPosition) => {
295
305
  const market = this.clearingHouse.getMarketAccount(
296
306
  marketPosition.marketIndex
297
307
  );
298
- const worstCaseBaseAssetAmount =
299
- calculateWorstCaseBaseAssetAmount(marketPosition);
300
308
 
301
- const worstCaseAssetValue = worstCaseBaseAssetAmount
302
- .abs()
303
- .mul(this.getOracleDataForMarket(market.marketIndex).price)
304
- .div(AMM_TO_QUOTE_PRECISION_RATIO.mul(MARK_PRICE_PRECISION));
309
+ if (marketPosition.lpShares.gt(ZERO)) {
310
+ // is an lp
311
+ // clone so we dont mutate the position
312
+ marketPosition = this.getClonedPosition(marketPosition);
305
313
 
306
- const marketMarginRatio = new BN(
307
- calculateMarketMarginRatio(
308
- market,
309
- worstCaseBaseAssetAmount.abs(),
310
- 'Initial'
311
- )
312
- );
313
- return marginRequirement.add(
314
- worstCaseAssetValue.mul(marketMarginRatio).div(MARGIN_PRECISION)
315
- );
316
- },
317
- ZERO
318
- );
314
+ // settle position
315
+ const [settledPosition, dustBaa, _] = this.getSettledLPPosition(
316
+ market.marketIndex
317
+ );
318
+ marketPosition.baseAssetAmount =
319
+ settledPosition.baseAssetAmount.add(dustBaa);
320
+ marketPosition.quoteAssetAmount = settledPosition.quoteAssetAmount;
321
+
322
+ // open orders
323
+ let openAsks;
324
+ if (market.amm.maxBaseAssetReserve > market.amm.baseAssetReserve) {
325
+ openAsks = market.amm.maxBaseAssetReserve
326
+ .sub(market.amm.baseAssetReserve)
327
+ .mul(marketPosition.lpShares)
328
+ .div(market.amm.sqrtK)
329
+ .mul(new BN(-1));
330
+ } else {
331
+ openAsks = ZERO;
332
+ }
319
333
 
320
- const bankMarginRequirement = this.getBankLiabilityValue(
321
- undefined,
322
- 'Initial'
323
- );
334
+ let openBids;
335
+ if (market.amm.minBaseAssetReserve < market.amm.baseAssetReserve) {
336
+ openBids = market.amm.baseAssetReserve
337
+ .sub(market.amm.minBaseAssetReserve)
338
+ .mul(marketPosition.lpShares)
339
+ .div(market.amm.sqrtK);
340
+ } else {
341
+ openBids = ZERO;
342
+ }
324
343
 
325
- return bankMarginRequirement.add(postionMarginRequirement);
326
- }
344
+ marketPosition.openAsks = marketPosition.openAsks.add(openAsks);
345
+ marketPosition.openBids = marketPosition.openBids.add(openBids);
346
+ }
327
347
 
328
- /**
329
- * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
330
- */
331
- public getMaintenanceMarginRequirement(): BN {
332
- return this.getUserAccount()
333
- .positions.reduce((marginRequirement, marketPosition) => {
334
- const market = this.clearingHouse.getMarketAccount(
335
- marketPosition.marketIndex
336
- );
337
348
  const worstCaseBaseAssetAmount =
338
349
  calculateWorstCaseBaseAssetAmount(marketPosition);
339
350
 
@@ -349,14 +360,28 @@ export class ClearingHouseUser {
349
360
  calculateMarketMarginRatio(
350
361
  market,
351
362
  worstCaseBaseAssetAmount.abs(),
352
- 'Maintenance'
363
+ type
353
364
  )
354
365
  )
355
366
  )
356
367
  .div(MARGIN_PRECISION)
357
368
  );
358
369
  }, ZERO)
359
- .add(this.getBankLiabilityValue(undefined, 'Maintenance'));
370
+ .add(this.getBankLiabilityValue(undefined, type));
371
+ }
372
+
373
+ /**
374
+ * @returns The initial margin requirement in USDC. : QUOTE_PRECISION
375
+ */
376
+ public getInitialMarginRequirement(): BN {
377
+ return this.getMarginRequirement('Initial');
378
+ }
379
+
380
+ /**
381
+ * @returns The maintenance margin requirement in USDC. : QUOTE_PRECISION
382
+ */
383
+ public getMaintenanceMarginRequirement(): BN {
384
+ return this.getMarginRequirement('Maintenance');
360
385
  }
361
386
 
362
387
  /**
@@ -372,11 +397,11 @@ export class ClearingHouseUser {
372
397
  .positions.filter((pos) =>
373
398
  marketIndex ? pos.marketIndex === marketIndex : true
374
399
  )
375
- .reduce((pnl, marketPosition) => {
400
+ .reduce((unrealizedPnl, marketPosition) => {
376
401
  const market = this.clearingHouse.getMarketAccount(
377
402
  marketPosition.marketIndex
378
403
  );
379
- let pnl0 = calculatePositionPNL(
404
+ let positionUnrealizedPnl = calculatePositionPNL(
380
405
  market,
381
406
  marketPosition,
382
407
  withFunding,
@@ -384,12 +409,12 @@ export class ClearingHouseUser {
384
409
  );
385
410
 
386
411
  if (withWeightMarginCategory !== undefined) {
387
- if (pnl0.gt(ZERO)) {
388
- pnl0 = pnl0
412
+ if (positionUnrealizedPnl.gt(ZERO)) {
413
+ positionUnrealizedPnl = positionUnrealizedPnl
389
414
  .mul(
390
- calculateUnsettledAssetWeight(
415
+ calculateUnrealizedAssetWeight(
391
416
  market,
392
- pnl0,
417
+ positionUnrealizedPnl,
393
418
  withWeightMarginCategory
394
419
  )
395
420
  )
@@ -397,7 +422,7 @@ export class ClearingHouseUser {
397
422
  }
398
423
  }
399
424
 
400
- return pnl.add(pnl0);
425
+ return unrealizedPnl.add(positionUnrealizedPnl);
401
426
  }, ZERO);
402
427
  }
403
428
 
@@ -528,47 +553,9 @@ export class ClearingHouseUser {
528
553
  * @returns : Precision QUOTE_PRECISION
529
554
  */
530
555
  public getTotalCollateral(marginCategory: MarginCategory = 'Initial'): BN {
531
- return this.getUserAccount()
532
- .bankBalances.reduce((totalAssetValue, bankBalance) => {
533
- if (
534
- bankBalance.balance.eq(ZERO) ||
535
- isVariant(bankBalance.balanceType, 'borrow')
536
- ) {
537
- return totalAssetValue;
538
- }
539
-
540
- // Todo this needs to account for whether it's based on initial or maintenance requirements
541
- const bankAccount: BankAccount = this.clearingHouse.getBankAccount(
542
- bankBalance.bankIndex
543
- );
544
-
545
- const tokenAmount = getTokenAmount(
546
- bankBalance.balance,
547
- bankAccount,
548
- bankBalance.balanceType
549
- );
550
-
551
- const weight = calculateAssetWeight(
552
- tokenAmount,
553
- bankAccount,
554
- marginCategory
555
- );
556
-
557
- return totalAssetValue.add(
558
- tokenAmount
559
- .mul(this.getOracleDataForBank(bankAccount.bankIndex).price)
560
- .mul(weight)
561
- .div(BANK_WEIGHT_PRECISION)
562
- .div(MARK_PRICE_PRECISION)
563
- // Adjust for decimals of bank account
564
- .div(
565
- new BN(10).pow(
566
- new BN(bankAccount.decimals).sub(BANK_BALANCE_PRECISION_EXP)
567
- )
568
- )
569
- );
570
- }, ZERO)
571
- .add(this.getUnrealizedPNL(true, undefined, marginCategory));
556
+ return this.getBankAssetValue(undefined, marginCategory).add(
557
+ this.getUnrealizedPNL(true, undefined, marginCategory)
558
+ );
572
559
  }
573
560
 
574
561
  /**
@@ -4,7 +4,11 @@ import { DataAndSlot, UserStatsAccountSubscriber } from './accounts/types';
4
4
  import { ClearingHouseUserStatsConfig } from './clearingHouseUserStatsConfig';
5
5
  import { PollingUserStatsAccountSubscriber } from './accounts/pollingUserStatsAccountSubscriber';
6
6
  import { WebSocketUserStatsAccountSubscriber } from './accounts/webSocketUserStatsAccountSubsriber';
7
- import { UserStatsAccount } from './types';
7
+ import { ReferrerInfo, UserStatsAccount } from './types';
8
+ import {
9
+ getUserAccountPublicKeySync,
10
+ getUserStatsAccountPublicKey,
11
+ } from './addresses/pda';
8
12
 
9
13
  export class ClearingHouseUserStats {
10
14
  clearingHouse: ClearingHouse;
@@ -50,4 +54,22 @@ export class ClearingHouseUserStats {
50
54
  public getAccount(): UserStatsAccount {
51
55
  return this.accountSubscriber.getUserStatsAccountAndSlot().data;
52
56
  }
57
+
58
+ public getReferrerInfo(): ReferrerInfo | undefined {
59
+ if (this.getAccount().referrer.equals(PublicKey.default)) {
60
+ return undefined;
61
+ } else {
62
+ return {
63
+ referrer: getUserAccountPublicKeySync(
64
+ this.clearingHouse.program.programId,
65
+ this.getAccount().referrer,
66
+ 0
67
+ ),
68
+ referrerStats: getUserStatsAccountPublicKey(
69
+ this.clearingHouse.program.programId,
70
+ this.getAccount().referrer
71
+ ),
72
+ };
73
+ }
74
+ }
53
75
  }