@drift-labs/sdk 0.2.0-master.9 → 0.2.0-temp.2

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 (61) hide show
  1. package/lib/admin.d.ts +3 -3
  2. package/lib/admin.js +6 -6
  3. package/lib/clearingHouse.d.ts +15 -4
  4. package/lib/clearingHouse.js +200 -37
  5. package/lib/clearingHouseUser.d.ts +2 -2
  6. package/lib/clearingHouseUser.js +8 -17
  7. package/lib/config.js +1 -1
  8. package/lib/constants/banks.js +2 -3
  9. package/lib/constants/numericConstants.d.ts +1 -0
  10. package/lib/constants/numericConstants.js +2 -1
  11. package/lib/events/eventList.d.ts +1 -0
  12. package/lib/events/eventList.js +10 -0
  13. package/lib/events/txEventCache.d.ts +2 -0
  14. package/lib/events/txEventCache.js +14 -0
  15. package/lib/idl/clearing_house.json +484 -103
  16. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  17. package/lib/index.d.ts +1 -1
  18. package/lib/index.js +1 -1
  19. package/lib/orders.js +1 -1
  20. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +7 -5
  21. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +41 -40
  22. package/lib/types.d.ts +62 -13
  23. package/lib/types.js +12 -1
  24. package/lib/util/computeUnits.js +1 -1
  25. package/package.json +1 -1
  26. package/src/admin.js +517 -0
  27. package/src/admin.ts +7 -7
  28. package/src/clearingHouse.ts +335 -47
  29. package/src/clearingHouseConfig.js +2 -0
  30. package/src/clearingHouseUser.ts +12 -23
  31. package/src/clearingHouseUserConfig.js +2 -0
  32. package/src/config.js +67 -0
  33. package/src/config.ts +1 -1
  34. package/src/constants/banks.js +42 -0
  35. package/src/constants/banks.ts +2 -3
  36. package/src/constants/markets.js +42 -0
  37. package/src/constants/numericConstants.js +41 -0
  38. package/src/constants/numericConstants.ts +1 -0
  39. package/src/events/eventList.ts +10 -0
  40. package/src/events/txEventCache.ts +16 -0
  41. package/src/factory/bigNum.js +37 -11
  42. package/src/idl/clearing_house.json +484 -103
  43. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  44. package/src/index.js +1 -1
  45. package/src/index.ts +1 -1
  46. package/src/mockUSDCFaucet.js +276 -167
  47. package/src/orders.ts +2 -1
  48. package/src/tokenFaucet.js +189 -0
  49. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +48 -59
  50. package/src/types.js +12 -1
  51. package/src/types.ts +63 -13
  52. package/src/{accounts/fetch.js → util/computeUnits.js} +11 -13
  53. package/src/util/computeUnits.ts +1 -1
  54. package/src/util/getTokenAddress.js +9 -0
  55. package/src/addresses/pda.js +0 -104
  56. package/src/math/bankBalance.js +0 -75
  57. package/src/math/market.js +0 -57
  58. package/src/math/orders.js +0 -110
  59. package/src/math/position.js +0 -140
  60. package/src/orders.js +0 -134
  61. package/src/tx/retryTxSender.js +0 -188
package/lib/admin.d.ts CHANGED
@@ -5,8 +5,8 @@ import { BN } from '@project-serum/anchor';
5
5
  import { ClearingHouse } from './clearingHouse';
6
6
  export declare class Admin extends ClearingHouse {
7
7
  initialize(usdcMint: PublicKey, adminControlsPrices: boolean): Promise<[TransactionSignature]>;
8
- initializeBank(mint: PublicKey, optimalUtilization: BN, optimalRate: BN, maxRate: BN, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: BN, maintenanceAssetWeight: BN, initialLiabilityWeight: BN, maintenanceLiabilityWeight: BN, imfFactor?: BN): Promise<TransactionSignature>;
9
- initializeMarket(priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioPartial?: number, marginRatioMaintenance?: number): Promise<TransactionSignature>;
8
+ initializeBank(mint: PublicKey, optimalUtilization: BN, optimalRate: BN, maxRate: BN, oracle: PublicKey, oracleSource: OracleSource, initialAssetWeight: BN, maintenanceAssetWeight: BN, initialLiabilityWeight: BN, maintenanceLiabilityWeight: BN, imfFactor?: BN, liquidationFee?: BN): Promise<TransactionSignature>;
9
+ initializeMarket(priceOracle: PublicKey, baseAssetReserve: BN, quoteAssetReserve: BN, periodicity: BN, pegMultiplier?: BN, oracleSource?: OracleSource, marginRatioInitial?: number, marginRatioMaintenance?: number, liquidationFee?: BN): Promise<TransactionSignature>;
10
10
  moveAmmPrice(baseAssetReserve: BN, quoteAssetReserve: BN, marketIndex: BN): Promise<TransactionSignature>;
11
11
  updateK(sqrtK: BN, marketIndex: BN): Promise<TransactionSignature>;
12
12
  moveAmmToPrice(marketIndex: BN, targetPrice: BN): Promise<TransactionSignature>;
@@ -18,7 +18,7 @@ export declare class Admin extends ClearingHouse {
18
18
  withdrawFromInsuranceVaultToMarket(marketIndex: BN, amount: BN): Promise<TransactionSignature>;
19
19
  updateAdmin(admin: PublicKey): Promise<TransactionSignature>;
20
20
  updateCurveUpdateIntensity(marketIndex: BN, curveUpdateIntensity: number): Promise<TransactionSignature>;
21
- updateMarginRatio(marketIndex: BN, marginRatioInitial: number, marginRatioPartial: number, marginRatioMaintenance: number): Promise<TransactionSignature>;
21
+ updateMarginRatio(marketIndex: BN, marginRatioInitial: number, marginRatioMaintenance: number): Promise<TransactionSignature>;
22
22
  updateMarketBaseSpread(marketIndex: BN, baseSpread: number): Promise<TransactionSignature>;
23
23
  updateMarketMaxSpread(marketIndex: BN, maxSpread: number): Promise<TransactionSignature>;
24
24
  updatePartialLiquidationClosePercentage(numerator: BN, denominator: BN): Promise<TransactionSignature>;
package/lib/admin.js CHANGED
@@ -58,12 +58,12 @@ class Admin extends clearingHouse_1.ClearingHouse {
58
58
  const { txSig: initializeTxSig } = await this.txSender.send(initializeTx, [], this.opts);
59
59
  return [initializeTxSig];
60
60
  }
61
- async initializeBank(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = new anchor_1.BN(0)) {
61
+ async initializeBank(mint, optimalUtilization, optimalRate, maxRate, oracle, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor = new anchor_1.BN(0), liquidationFee = numericConstants_1.ZERO) {
62
62
  const bankIndex = this.getStateAccount().numberOfBanks;
63
63
  const bank = await (0, pda_1.getBankPublicKey)(this.program.programId, bankIndex);
64
64
  const bankVault = await (0, pda_1.getBankVaultPublicKey)(this.program.programId, bankIndex);
65
65
  const bankVaultAuthority = await (0, pda_1.getBankVaultAuthorityPublicKey)(this.program.programId, bankIndex);
66
- const initializeTx = await this.program.transaction.initializeBank(optimalUtilization, optimalRate, maxRate, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor, {
66
+ const initializeTx = await this.program.transaction.initializeBank(optimalUtilization, optimalRate, maxRate, oracleSource, initialAssetWeight, maintenanceAssetWeight, initialLiabilityWeight, maintenanceLiabilityWeight, imfFactor, liquidationFee, {
67
67
  accounts: {
68
68
  admin: this.wallet.publicKey,
69
69
  state: await this.getStatePublicKey(),
@@ -85,9 +85,9 @@ class Admin extends clearingHouse_1.ClearingHouse {
85
85
  });
86
86
  return txSig;
87
87
  }
88
- async initializeMarket(priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioPartial = 625, marginRatioMaintenance = 500) {
88
+ async initializeMarket(priceOracle, baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier = numericConstants_1.PEG_PRECISION, oracleSource = types_1.OracleSource.PYTH, marginRatioInitial = 2000, marginRatioMaintenance = 500, liquidationFee = numericConstants_1.ZERO) {
89
89
  const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, this.getStateAccount().numberOfMarkets);
90
- const initializeMarketTx = await this.program.transaction.initializeMarket(baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, oracleSource, marginRatioInitial, marginRatioPartial, marginRatioMaintenance, {
90
+ const initializeMarketTx = await this.program.transaction.initializeMarket(baseAssetReserve, quoteAssetReserve, periodicity, pegMultiplier, oracleSource, marginRatioInitial, marginRatioMaintenance, liquidationFee, {
91
91
  accounts: {
92
92
  state: await this.getStatePublicKey(),
93
93
  admin: this.wallet.publicKey,
@@ -242,8 +242,8 @@ class Admin extends clearingHouse_1.ClearingHouse {
242
242
  },
243
243
  });
244
244
  }
245
- async updateMarginRatio(marketIndex, marginRatioInitial, marginRatioPartial, marginRatioMaintenance) {
246
- return await this.program.rpc.updateMarginRatio(marginRatioInitial, marginRatioPartial, marginRatioMaintenance, {
245
+ async updateMarginRatio(marketIndex, marginRatioInitial, marginRatioMaintenance) {
246
+ return await this.program.rpc.updateMarginRatio(marginRatioInitial, marginRatioMaintenance, {
247
247
  accounts: {
248
248
  admin: this.wallet.publicKey,
249
249
  state: await this.getStatePublicKey(),
@@ -3,7 +3,7 @@
3
3
  import { AnchorProvider, BN, Program } from '@project-serum/anchor';
4
4
  import { StateAccount, IWallet, PositionDirection, UserAccount, MarketAccount, OrderParams, Order, BankAccount, UserBankBalance, MakerInfo, TakerInfo, OptionalOrderParams } from './types';
5
5
  import { Connection, PublicKey, TransactionSignature, ConfirmOptions, TransactionInstruction, AccountMeta } from '@solana/web3.js';
6
- import { MockUSDCFaucet } from './mockUSDCFaucet';
6
+ import { TokenFaucet } from './tokenFaucet';
7
7
  import { EventEmitter } from 'events';
8
8
  import StrictEventEmitter from 'strict-event-emitter-types';
9
9
  import { ClearingHouseAccountSubscriber, ClearingHouseAccountEvents, DataAndSlot } from './accounts/types';
@@ -87,7 +87,7 @@ export declare class ClearingHouse {
87
87
  * @returns
88
88
  */
89
89
  initializeUserAccountAndDepositCollateral(amount: BN, userTokenAccount: PublicKey, bankIndex?: BN, userId?: number, name?: string, fromUserId?: number): Promise<[TransactionSignature, PublicKey]>;
90
- initializeUserAccountForDevnet(userId: number, name: string, mockUSDCFaucet: MockUSDCFaucet, amount: BN): Promise<[TransactionSignature, PublicKey]>;
90
+ initializeUserAccountForDevnet(userId: number, name: string, bankIndex: BN, tokenFaucet: TokenFaucet, amount: BN): Promise<[TransactionSignature, PublicKey]>;
91
91
  withdraw(amount: BN, bankIndex: BN, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionSignature>;
92
92
  getWithdrawIx(amount: BN, bankIndex: BN, userTokenAccount: PublicKey, reduceOnly?: boolean): Promise<TransactionInstruction>;
93
93
  transferDeposit(amount: BN, bankIndex: BN, fromUserId: number, toUserId: number): Promise<TransactionSignature>;
@@ -124,8 +124,19 @@ export declare class ClearingHouse {
124
124
  }[], marketIndex: BN): Promise<TransactionSignature>;
125
125
  settlePNL(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: BN): Promise<TransactionSignature>;
126
126
  settlePNLIx(settleeUserAccountPublicKey: PublicKey, settleeUserAccount: UserAccount, marketIndex: BN): Promise<TransactionInstruction>;
127
- liquidate(liquidateeUserAccountPublicKey: PublicKey): Promise<TransactionSignature>;
128
- getLiquidateIx(liquidateeUserAccountPublicKey: PublicKey): Promise<TransactionInstruction>;
127
+ liquidatePerp(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: BN, maxBaseAssetAmount: BN): Promise<TransactionSignature>;
128
+ getLiquidatePerpIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, marketIndex: BN, maxBaseAssetAmount: BN): Promise<TransactionInstruction>;
129
+ liquidateBorrow(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetBankIndex: BN, liabilityBankIndex: BN, maxLiabilityTransfer: BN): Promise<TransactionSignature>;
130
+ getLiquidateBorrowIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, assetBankIndex: BN, liabilityBankIndex: BN, maxLiabilityTransfer: BN): Promise<TransactionInstruction>;
131
+ liquidateBorrowForPerpPnl(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: BN, liabilityBankIndex: BN, maxLiabilityTransfer: BN): Promise<TransactionSignature>;
132
+ getLiquidateBorrowForPerpPnlIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: BN, liabilityBankIndex: BN, maxLiabilityTransfer: BN): Promise<TransactionInstruction>;
133
+ liquidatePerpPnlForDeposit(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: BN, assetBankIndex: BN, maxPnlTransfer: BN): Promise<TransactionSignature>;
134
+ getLiquidatePerpPnlForDepositIx(userAccountPublicKey: PublicKey, userAccount: UserAccount, perpMarketIndex: BN, assetBankIndex: BN, maxPnlTransfer: BN): Promise<TransactionInstruction>;
135
+ getRemainingAccountsForLiquidation(params: {
136
+ userAccount: UserAccount;
137
+ writableMarketIndex?: BN;
138
+ writableBankIndexes?: BN[];
139
+ }): AccountMeta[];
129
140
  updateFundingRate(oracle: PublicKey, marketIndex: BN): Promise<TransactionSignature>;
130
141
  getUpdateFundingRateIx(oracle: PublicKey, marketIndex: BN): Promise<TransactionInstruction>;
131
142
  settleFundingPayment(userAccount: PublicKey): Promise<TransactionSignature>;
@@ -419,10 +419,10 @@ class ClearingHouse {
419
419
  const { txSig } = await this.txSender.send(tx, []);
420
420
  return [txSig, userAccountPublicKey];
421
421
  }
422
- async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, mockUSDCFaucet, amount) {
423
- const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await mockUSDCFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
422
+ async initializeUserAccountForDevnet(userId = 0, name = userName_1.DEFAULT_USER_NAME, bankIndex, tokenFaucet, amount) {
423
+ const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = await tokenFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
424
424
  const [userAccountPublicKey, initializeUserAccountIx] = await this.getInitializeUserInstructions(userId, name);
425
- const depositCollateralIx = await this.getDepositInstruction(amount, new anchor_1.BN(0), associateTokenPublicKey, userId, false, false);
425
+ const depositCollateralIx = await this.getDepositInstruction(amount, bankIndex, associateTokenPublicKey, userId, false, false);
426
426
  const tx = new web3_js_1.Transaction()
427
427
  .add(createAssociatedAccountIx)
428
428
  .add(mintToIx)
@@ -891,54 +891,217 @@ class ClearingHouse {
891
891
  remainingAccounts: remainingAccounts,
892
892
  });
893
893
  }
894
- async liquidate(liquidateeUserAccountPublicKey) {
895
- const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateIx(liquidateeUserAccountPublicKey)), [], this.opts);
894
+ async liquidatePerp(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
895
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount)), [], this.opts);
896
896
  return txSig;
897
897
  }
898
- async getLiquidateIx(liquidateeUserAccountPublicKey) {
899
- const userAccountPublicKey = await this.getUserAccountPublicKey();
900
- const liquidateeUserAccount = (await this.program.account.user.fetch(liquidateeUserAccountPublicKey));
901
- const bankAccountInfos = [
902
- {
903
- pubkey: this.getQuoteAssetBankAccount().pubkey,
904
- isSigner: false,
905
- isWritable: true,
898
+ async getLiquidatePerpIx(userAccountPublicKey, userAccount, marketIndex, maxBaseAssetAmount) {
899
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
900
+ const remainingAccounts = this.getRemainingAccountsForLiquidation({
901
+ writableMarketIndex: marketIndex,
902
+ userAccount,
903
+ });
904
+ return await this.program.instruction.liquidatePerp(marketIndex, maxBaseAssetAmount, {
905
+ accounts: {
906
+ state: await this.getStatePublicKey(),
907
+ authority: this.wallet.publicKey,
908
+ user: userAccountPublicKey,
909
+ liquidator: liquidatorPublicKey,
906
910
  },
907
- ];
908
- const marketAccountInfos = [];
909
- const oracleAccountInfos = [];
911
+ remainingAccounts: remainingAccounts,
912
+ });
913
+ }
914
+ async liquidateBorrow(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer) {
915
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer)), [], this.opts);
916
+ return txSig;
917
+ }
918
+ async getLiquidateBorrowIx(userAccountPublicKey, userAccount, assetBankIndex, liabilityBankIndex, maxLiabilityTransfer) {
919
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
920
+ const remainingAccounts = this.getRemainingAccountsForLiquidation({
921
+ userAccount,
922
+ writableBankIndexes: [liabilityBankIndex, assetBankIndex],
923
+ });
924
+ return await this.program.instruction.liquidateBorrow(assetBankIndex, liabilityBankIndex, maxLiabilityTransfer, {
925
+ accounts: {
926
+ state: await this.getStatePublicKey(),
927
+ authority: this.wallet.publicKey,
928
+ user: userAccountPublicKey,
929
+ liquidator: liquidatorPublicKey,
930
+ },
931
+ remainingAccounts: remainingAccounts,
932
+ });
933
+ }
934
+ async liquidateBorrowForPerpPnl(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer) {
935
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer)), [], this.opts);
936
+ return txSig;
937
+ }
938
+ async getLiquidateBorrowForPerpPnlIx(userAccountPublicKey, userAccount, perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer) {
939
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
940
+ const remainingAccounts = this.getRemainingAccountsForLiquidation({
941
+ userAccount,
942
+ writableMarketIndex: perpMarketIndex,
943
+ writableBankIndexes: [liabilityBankIndex],
944
+ });
945
+ return await this.program.instruction.liquidateBorrowForPerpPnl(perpMarketIndex, liabilityBankIndex, maxLiabilityTransfer, {
946
+ accounts: {
947
+ state: await this.getStatePublicKey(),
948
+ authority: this.wallet.publicKey,
949
+ user: userAccountPublicKey,
950
+ liquidator: liquidatorPublicKey,
951
+ },
952
+ remainingAccounts: remainingAccounts,
953
+ });
954
+ }
955
+ async liquidatePerpPnlForDeposit(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer) {
956
+ const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer)), [], this.opts);
957
+ return txSig;
958
+ }
959
+ async getLiquidatePerpPnlForDepositIx(userAccountPublicKey, userAccount, perpMarketIndex, assetBankIndex, maxPnlTransfer) {
960
+ const liquidatorPublicKey = await this.getUserAccountPublicKey();
961
+ const remainingAccounts = this.getRemainingAccountsForLiquidation({
962
+ userAccount,
963
+ writableMarketIndex: perpMarketIndex,
964
+ writableBankIndexes: [assetBankIndex],
965
+ });
966
+ return await this.program.instruction.liquidatePerpPnlForDeposit(perpMarketIndex, assetBankIndex, maxPnlTransfer, {
967
+ accounts: {
968
+ state: await this.getStatePublicKey(),
969
+ authority: this.wallet.publicKey,
970
+ user: userAccountPublicKey,
971
+ liquidator: liquidatorPublicKey,
972
+ },
973
+ remainingAccounts: remainingAccounts,
974
+ });
975
+ }
976
+ getRemainingAccountsForLiquidation(params) {
977
+ const liquidateeUserAccount = params.userAccount;
978
+ const oracleAccountMap = new Map();
979
+ const bankAccountMap = new Map();
980
+ const marketAccountMap = new Map();
981
+ for (const bankBalance of liquidateeUserAccount.bankBalances) {
982
+ if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
983
+ const bankAccount = this.getBankAccount(bankBalance.bankIndex);
984
+ bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
985
+ pubkey: bankAccount.pubkey,
986
+ isSigner: false,
987
+ isWritable: false,
988
+ });
989
+ if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
990
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
991
+ pubkey: bankAccount.oracle,
992
+ isSigner: false,
993
+ isWritable: false,
994
+ });
995
+ }
996
+ }
997
+ }
910
998
  for (const position of liquidateeUserAccount.positions) {
911
999
  if (!(0, position_1.positionIsAvailable)(position)) {
912
1000
  const market = this.getMarketAccount(position.marketIndex);
913
- const marketPublicKey = await (0, pda_1.getMarketPublicKey)(this.program.programId, position.marketIndex);
914
- marketAccountInfos.push({
915
- pubkey: marketPublicKey,
916
- isWritable: true,
1001
+ marketAccountMap.set(position.marketIndex.toNumber(), {
1002
+ pubkey: market.pubkey,
1003
+ isWritable: false,
917
1004
  isSigner: false,
918
1005
  });
919
- oracleAccountInfos.push({
1006
+ oracleAccountMap.set(market.amm.oracle.toString(), {
920
1007
  pubkey: market.amm.oracle,
921
1008
  isWritable: false,
922
1009
  isSigner: false,
923
1010
  });
924
1011
  }
925
1012
  }
926
- const remainingAccounts = oracleAccountInfos.concat(bankAccountInfos.concat(marketAccountInfos));
927
- const state = this.getStateAccount();
928
- const quoteAssetBankAccount = this.getQuoteAssetBankAccount();
929
- return await this.program.instruction.liquidate({
930
- accounts: {
931
- state: await this.getStatePublicKey(),
932
- authority: this.wallet.publicKey,
933
- user: liquidateeUserAccountPublicKey,
934
- liquidator: userAccountPublicKey,
935
- bankVault: quoteAssetBankAccount.vault,
936
- bankVaultAuthority: quoteAssetBankAccount.vaultAuthority,
937
- insuranceVault: state.insuranceVault,
938
- tokenProgram: spl_token_1.TOKEN_PROGRAM_ID,
939
- },
940
- remainingAccounts: remainingAccounts,
941
- });
1013
+ const userAccountAndSlot = this.getUserAccountAndSlot();
1014
+ if (!userAccountAndSlot) {
1015
+ throw Error('No user account found. Most likely user account does not exist or failed to fetch account');
1016
+ }
1017
+ const { data: userAccount, slot: lastUserPositionsSlot } = userAccountAndSlot;
1018
+ for (const [marketIndexNum, slot] of this.marketLastSlotCache.entries()) {
1019
+ // if cache has more recent slot than user positions account slot, add market to remaining accounts
1020
+ // otherwise remove from slot
1021
+ if (slot > lastUserPositionsSlot) {
1022
+ const marketAccount = this.getMarketAccount(marketIndexNum);
1023
+ marketAccountMap.set(marketIndexNum, {
1024
+ pubkey: marketAccount.pubkey,
1025
+ isSigner: false,
1026
+ isWritable: false,
1027
+ });
1028
+ oracleAccountMap.set(marketAccount.amm.oracle.toString(), {
1029
+ pubkey: marketAccount.amm.oracle,
1030
+ isSigner: false,
1031
+ isWritable: false,
1032
+ });
1033
+ }
1034
+ else {
1035
+ this.marketLastSlotCache.delete(marketIndexNum);
1036
+ }
1037
+ }
1038
+ for (const bankBalance of userAccount.bankBalances) {
1039
+ if (!bankBalance.balance.eq(numericConstants_1.ZERO)) {
1040
+ const bankAccount = this.getBankAccount(bankBalance.bankIndex);
1041
+ bankAccountMap.set(bankBalance.bankIndex.toNumber(), {
1042
+ pubkey: bankAccount.pubkey,
1043
+ isSigner: false,
1044
+ isWritable: false,
1045
+ });
1046
+ if (!bankAccount.oracle.equals(web3_js_1.PublicKey.default)) {
1047
+ oracleAccountMap.set(bankAccount.oracle.toString(), {
1048
+ pubkey: bankAccount.oracle,
1049
+ isSigner: false,
1050
+ isWritable: false,
1051
+ });
1052
+ }
1053
+ }
1054
+ }
1055
+ for (const position of userAccount.positions) {
1056
+ if (!(0, position_1.positionIsAvailable)(position)) {
1057
+ const market = this.getMarketAccount(position.marketIndex);
1058
+ marketAccountMap.set(position.marketIndex.toNumber(), {
1059
+ pubkey: market.pubkey,
1060
+ isWritable: false,
1061
+ isSigner: false,
1062
+ });
1063
+ oracleAccountMap.set(market.amm.oracle.toString(), {
1064
+ pubkey: market.amm.oracle,
1065
+ isWritable: false,
1066
+ isSigner: false,
1067
+ });
1068
+ }
1069
+ }
1070
+ if (params.writableMarketIndex) {
1071
+ const market = this.getMarketAccount(params.writableMarketIndex);
1072
+ marketAccountMap.set(market.marketIndex.toNumber(), {
1073
+ pubkey: market.pubkey,
1074
+ isSigner: false,
1075
+ isWritable: true,
1076
+ });
1077
+ oracleAccountMap.set(market.amm.oracle.toString(), {
1078
+ pubkey: market.amm.oracle,
1079
+ isSigner: false,
1080
+ isWritable: false,
1081
+ });
1082
+ }
1083
+ if (params.writableBankIndexes) {
1084
+ for (const writableBankIndex of params.writableBankIndexes) {
1085
+ const bank = this.getBankAccount(writableBankIndex);
1086
+ bankAccountMap.set(bank.bankIndex.toNumber(), {
1087
+ pubkey: bank.pubkey,
1088
+ isSigner: false,
1089
+ isWritable: true,
1090
+ });
1091
+ if (!bank.oracle.equals(web3_js_1.PublicKey.default)) {
1092
+ oracleAccountMap.set(bank.oracle.toString(), {
1093
+ pubkey: bank.oracle,
1094
+ isSigner: false,
1095
+ isWritable: false,
1096
+ });
1097
+ }
1098
+ }
1099
+ }
1100
+ return [
1101
+ ...oracleAccountMap.values(),
1102
+ ...bankAccountMap.values(),
1103
+ ...marketAccountMap.values(),
1104
+ ];
942
1105
  }
943
1106
  async updateFundingRate(oracle, marketIndex) {
944
1107
  const { txSig } = await this.txSender.send((0, utils_1.wrapInTx)(await this.getUpdateFundingRateIx(oracle, marketIndex)), [], this.opts);
@@ -63,7 +63,7 @@ export declare class ClearingHouseUser {
63
63
  /**
64
64
  * @returns The partial margin requirement in USDC. : QUOTE_PRECISION
65
65
  */
66
- getPartialMarginRequirement(): BN;
66
+ getMaintenanceMarginRequirement(): BN;
67
67
  /**
68
68
  * calculates unrealized position price pnl
69
69
  * @returns : Precision QUOTE_PRECISION
@@ -132,7 +132,7 @@ export declare class ClearingHouseUser {
132
132
  * @param partial
133
133
  * @returns Precision : MARK_PRICE_PRECISION
134
134
  */
135
- liquidationPrice(marketPosition: Pick<UserPosition, 'marketIndex'>, positionBaseSizeChange?: BN, partial?: boolean): BN;
135
+ liquidationPrice(marketPosition: Pick<UserPosition, 'marketIndex'>, positionBaseSizeChange?: BN): BN;
136
136
  /**
137
137
  * Calculates the estimated liquidation price for a position after closing a quote amount of the position.
138
138
  * @param positionMarketIndex
@@ -126,12 +126,12 @@ class ClearingHouseUser {
126
126
  /**
127
127
  * @returns The partial margin requirement in USDC. : QUOTE_PRECISION
128
128
  */
129
- getPartialMarginRequirement() {
129
+ getMaintenanceMarginRequirement() {
130
130
  return this.getUserAccount()
131
131
  .positions.reduce((marginRequirement, marketPosition) => {
132
132
  const market = this.clearingHouse.getMarketAccount(marketPosition.marketIndex);
133
133
  return marginRequirement.add((0, _1.calculateBaseAssetValue)(market, marketPosition, this.getOracleDataForMarket(market.marketIndex))
134
- .mul(new _1.BN(market.marginRatioPartial))
134
+ .mul(new _1.BN(market.marginRatioMaintenance))
135
135
  .div(numericConstants_1.MARGIN_PRECISION));
136
136
  }, numericConstants_1.ZERO)
137
137
  .add(this.getTotalLiability());
@@ -319,9 +319,6 @@ class ClearingHouseUser {
319
319
  case 'Maintenance':
320
320
  marginRatioCategory = market.marginRatioMaintenance;
321
321
  break;
322
- case 'Partial':
323
- marginRatioCategory = market.marginRatioPartial;
324
- break;
325
322
  default:
326
323
  marginRatioCategory = market.marginRatioInitial;
327
324
  break;
@@ -342,7 +339,7 @@ class ClearingHouseUser {
342
339
  }
343
340
  canBeLiquidated() {
344
341
  const totalCollateral = this.getTotalCollateral();
345
- const partialMaintenanceRequirement = this.getPartialMarginRequirement();
342
+ const partialMaintenanceRequirement = this.getMaintenanceMarginRequirement();
346
343
  const marginRatio = this.getMarginRatio();
347
344
  const canLiquidate = totalCollateral.lt(partialMaintenanceRequirement);
348
345
  return [canLiquidate, marginRatio];
@@ -372,7 +369,7 @@ class ClearingHouseUser {
372
369
  * @param partial
373
370
  * @returns Precision : MARK_PRICE_PRECISION
374
371
  */
375
- liquidationPrice(marketPosition, positionBaseSizeChange = numericConstants_1.ZERO, partial = false) {
372
+ liquidationPrice(marketPosition, positionBaseSizeChange = numericConstants_1.ZERO) {
376
373
  // solves formula for example canBeLiquidated below
377
374
  /* example: assume BTC price is $40k (examine 10% up/down)
378
375
 
@@ -413,9 +410,7 @@ class ClearingHouseUser {
413
410
  const market = this.clearingHouse.getMarketAccount(position.marketIndex);
414
411
  const positionValue = (0, _1.calculateBaseAssetValue)(market, position, this.getOracleDataForMarket(market.marketIndex));
415
412
  const marketMarginRequirement = positionValue
416
- .mul(partial
417
- ? new _1.BN(market.marginRatioPartial)
418
- : new _1.BN(market.marginRatioMaintenance))
413
+ .mul(new _1.BN(market.marginRatioMaintenance))
419
414
  .div(numericConstants_1.MARGIN_PRECISION);
420
415
  totalMarginRequirement = totalMarginRequirement.add(marketMarginRequirement);
421
416
  }
@@ -428,14 +423,10 @@ class ClearingHouseUser {
428
423
  return new _1.BN(-1);
429
424
  }
430
425
  const marginRequirementAfterTrade = marginRequirementExcludingTargetMarket.add(proposedMarketPositionValue
431
- .mul(partial
432
- ? new _1.BN(market.marginRatioPartial)
433
- : new _1.BN(market.marginRatioMaintenance))
426
+ .mul(new _1.BN(market.marginRatioMaintenance))
434
427
  .div(numericConstants_1.MARGIN_PRECISION));
435
428
  const freeCollateralAfterTrade = totalCollateral.sub(marginRequirementAfterTrade);
436
- const marketMaxLeverage = partial
437
- ? this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Partial')
438
- : this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Maintenance');
429
+ const marketMaxLeverage = this.getMaxLeverage(proposedMarketPosition.marketIndex, 'Maintenance');
439
430
  let priceDelta;
440
431
  if (proposedBaseAssetAmount.lt(numericConstants_1.ZERO)) {
441
432
  priceDelta = freeCollateralAfterTrade
@@ -486,7 +477,7 @@ class ClearingHouseUser {
486
477
  .neg();
487
478
  return this.liquidationPrice({
488
479
  marketIndex: positionMarketIndex,
489
- }, closeBaseAmount, true);
480
+ }, closeBaseAmount);
490
481
  }
491
482
  /**
492
483
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
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: 'BMow898PH56jD8z4EaqxicoGXkR1HhN17qrER6Uc4AYq',
10
+ CLEARING_HOUSE_PROGRAM_ID: '4oyTJnAQ9FqJj1y9mPytbWsLeeHmBzGYfuFqypwyQvuh',
11
11
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
12
12
  MARKETS: markets_1.DevnetMarkets,
13
13
  BANKS: banks_1.DevnetBanks,
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Banks = exports.MainnetBanks = exports.DevnetBanks = void 0;
4
4
  const __1 = require("../");
5
5
  const web3_js_1 = require("@solana/web3.js");
6
- const token_instructions_1 = require("@project-serum/serum/lib/token-instructions");
7
6
  exports.DevnetBanks = [
8
7
  {
9
8
  symbol: 'USDC',
@@ -17,14 +16,14 @@ exports.DevnetBanks = [
17
16
  bankIndex: new __1.BN(1),
18
17
  oracle: new web3_js_1.PublicKey('J83w4HKfqxwcq3BEMMkPFSppX3gqekLyLJBexebFVkix'),
19
18
  oracleSource: __1.OracleSource.PYTH,
20
- mint: token_instructions_1.WRAPPED_SOL_MINT,
19
+ mint: new web3_js_1.PublicKey('So11111111111111111111111111111111111111112'),
21
20
  },
22
21
  {
23
22
  symbol: 'BTC',
24
23
  bankIndex: new __1.BN(2),
25
24
  oracle: new web3_js_1.PublicKey('HovQMDrbAgAYPCmHVSrezcSmkMtXSSUsLDFANExrZh2J'),
26
25
  oracleSource: __1.OracleSource.PYTH,
27
- mint: new web3_js_1.PublicKey('Gh9ZwEmdLJ8DscKNTkTqPbNwLNNBjuSzaG9Vp2KGtKJr'),
26
+ mint: new web3_js_1.PublicKey('3BZPwbcqB5kKScF3TEXxwNfx5ipV13kbRVDvfVp5c6fv'),
28
27
  },
29
28
  ];
30
29
  exports.MainnetBanks = [
@@ -21,6 +21,7 @@ export declare const BANK_RATE_PRECISION: BN;
21
21
  export declare const BANK_WEIGHT_PRECISION: BN;
22
22
  export declare const BANK_BALANCE_PRECISION_EXP: BN;
23
23
  export declare const BANK_BALANCE_PRECISION: BN;
24
+ export declare const LIQUIDATION_FEE_PRECISION: BN;
24
25
  export declare const QUOTE_PRECISION: BN;
25
26
  export declare const MARK_PRICE_PRECISION: BN;
26
27
  export declare const FUNDING_PAYMENT_PRECISION: BN;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.QUOTE_ASSET_BANK_INDEX = exports.ONE_YEAR = exports.BID_ASK_SPREAD_PRECISION = exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.BANK_BALANCE_PRECISION = exports.BANK_BALANCE_PRECISION_EXP = exports.BANK_WEIGHT_PRECISION = exports.BANK_RATE_PRECISION = exports.BANK_UTILIZATION_PRECISION = exports.BANK_CUMULATIVE_INTEREST_PRECISION = exports.BANK_INTEREST_PRECISION = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.MARK_PRICE_PRECISION_EXP = exports.FUNDING_PAYMENT_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
3
+ exports.QUOTE_ASSET_BANK_INDEX = exports.ONE_YEAR = exports.BID_ASK_SPREAD_PRECISION = exports.MARGIN_PRECISION = exports.AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO = exports.PRICE_TO_QUOTE_PRECISION = exports.PRICE_DIV_PEG = exports.AMM_TO_QUOTE_PRECISION_RATIO = exports.BASE_PRECISION_EXP = exports.BASE_PRECISION = exports.AMM_RESERVE_PRECISION = exports.PEG_PRECISION = exports.FUNDING_PAYMENT_PRECISION = exports.MARK_PRICE_PRECISION = exports.QUOTE_PRECISION = exports.LIQUIDATION_FEE_PRECISION = exports.BANK_BALANCE_PRECISION = exports.BANK_BALANCE_PRECISION_EXP = exports.BANK_WEIGHT_PRECISION = exports.BANK_RATE_PRECISION = exports.BANK_UTILIZATION_PRECISION = exports.BANK_CUMULATIVE_INTEREST_PRECISION = exports.BANK_INTEREST_PRECISION = exports.AMM_RESERVE_PRECISION_EXP = exports.PEG_PRECISION_EXP = exports.FUNDING_RATE_PRECISION_EXP = exports.MARK_PRICE_PRECISION_EXP = exports.FUNDING_PAYMENT_PRECISION_EXP = exports.QUOTE_PRECISION_EXP = exports.MAX_LEVERAGE = exports.TEN_MILLION = exports.BN_MAX = exports.TEN_THOUSAND = exports.TEN = exports.TWO = exports.ONE = exports.ZERO = void 0;
4
4
  const __1 = require("../");
5
5
  exports.ZERO = new __1.BN(0);
6
6
  exports.ONE = new __1.BN(1);
@@ -23,6 +23,7 @@ exports.BANK_RATE_PRECISION = new __1.BN(1000000);
23
23
  exports.BANK_WEIGHT_PRECISION = new __1.BN(100);
24
24
  exports.BANK_BALANCE_PRECISION_EXP = new __1.BN(6);
25
25
  exports.BANK_BALANCE_PRECISION = new __1.BN(10).pow(exports.BANK_BALANCE_PRECISION_EXP);
26
+ exports.LIQUIDATION_FEE_PRECISION = new __1.BN(1000000);
26
27
  exports.QUOTE_PRECISION = new __1.BN(10).pow(exports.QUOTE_PRECISION_EXP);
27
28
  exports.MARK_PRICE_PRECISION = new __1.BN(10).pow(exports.MARK_PRICE_PRECISION_EXP);
28
29
  exports.FUNDING_PAYMENT_PRECISION = new __1.BN(10).pow(exports.FUNDING_PAYMENT_PRECISION_EXP);
@@ -17,6 +17,7 @@ export declare class EventList<Type extends EventType> {
17
17
  insert(event: EventMap[Type]): void;
18
18
  detach(): void;
19
19
  toArray(): EventMap[Type][];
20
+ countNode(): number;
20
21
  [Symbol.iterator](): Generator<EventMap[Type], void, unknown>;
21
22
  }
22
23
  export {};
@@ -40,6 +40,9 @@ class EventList {
40
40
  if (currentNode.next !== undefined) {
41
41
  newNode.next.prev = newNode;
42
42
  }
43
+ else {
44
+ this.tail = newNode;
45
+ }
43
46
  currentNode.next = newNode;
44
47
  newNode.prev = currentNode;
45
48
  }
@@ -66,6 +69,13 @@ class EventList {
66
69
  toArray() {
67
70
  return Array.from(this);
68
71
  }
72
+ countNode() {
73
+ let count = 0;
74
+ for (const _node of this) {
75
+ count++;
76
+ }
77
+ return count;
78
+ }
69
79
  *[Symbol.iterator]() {
70
80
  let node = this.head;
71
81
  while (node) {
@@ -19,6 +19,8 @@ export declare class TxEventCache {
19
19
  has(key: string): boolean;
20
20
  get(key: string): WrappedEvent<EventType>[] | undefined;
21
21
  detach(node: Node): void;
22
+ countNode(): number;
23
+ [Symbol.iterator](): Generator<WrappedEvent<keyof import("./types").EventMap>[], void, unknown>;
22
24
  clear(): void;
23
25
  }
24
26
  export {};
@@ -61,6 +61,20 @@ class TxEventCache {
61
61
  this.tail = node.prev;
62
62
  }
63
63
  }
64
+ countNode() {
65
+ let count = 0;
66
+ for (const _node of this) {
67
+ count++;
68
+ }
69
+ return count;
70
+ }
71
+ *[Symbol.iterator]() {
72
+ let node = this.head;
73
+ while (node) {
74
+ yield node.value;
75
+ node = node.next;
76
+ }
77
+ }
64
78
  clear() {
65
79
  this.head = undefined;
66
80
  this.tail = undefined;