flash-sdk 1.0.4 → 1.0.5

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 (100) hide show
  1. package/lib/CustodyAccount.js +9 -19
  2. package/lib/OraclePrice.d.ts +2 -0
  3. package/lib/OraclePrice.js +4 -0
  4. package/lib/PerpetualsClient.d.ts +26 -5
  5. package/lib/PerpetualsClient.js +586 -24
  6. package/lib/PoolAccount.d.ts +2 -1
  7. package/lib/PoolAccount.js +16 -29
  8. package/lib/PoolConfig.d.ts +7 -2
  9. package/lib/PoolConfig.js +15 -7
  10. package/lib/PoolConfig.json +4 -0
  11. package/lib/{PoolDisplayData.d.ts → PoolDataClient.d.ts} +3 -2
  12. package/lib/{PoolDisplayData.js → PoolDataClient.js} +13 -13
  13. package/lib/PositionAccount.d.ts +1 -0
  14. package/lib/Token.js +1 -0
  15. package/lib/constants/index.d.ts +1 -0
  16. package/lib/idl/perpetuals.d.ts +3675 -0
  17. package/{src/target/types → lib/idl}/perpetuals.js +140 -3
  18. package/lib/index.d.ts +3 -0
  19. package/lib/index.js +5 -0
  20. package/lib/tsconfig.tsbuildinfo +1 -1
  21. package/lib/types/index.d.ts +5 -3
  22. package/lib/types/index.js +21 -1
  23. package/lib/utils/index.d.ts +2 -0
  24. package/lib/utils/index.js +57 -1
  25. package/lib/utils/rpc.d.ts +13 -0
  26. package/lib/utils/rpc.js +217 -0
  27. package/package.json +1 -1
  28. package/src/CustodyAccount.ts +24 -23
  29. package/src/OraclePrice.ts +4 -4
  30. package/src/PerpetualsClient.ts +737 -96
  31. package/src/PoolAccount.ts +34 -32
  32. package/src/PoolConfig.json +4 -0
  33. package/src/PoolConfig.ts +21 -6
  34. package/src/{PoolDisplayData.ts → PoolDataClient.ts} +2 -2
  35. package/src/Token.ts +1 -0
  36. package/src/{target/types → idl}/perpetuals.ts +280 -6
  37. package/src/index.ts +3 -0
  38. package/src/types/index.ts +26 -3
  39. package/src/utils/index.ts +14 -0
  40. package/src/utils/rpc.ts +162 -0
  41. package/lib/CustodyAccount.d.ts.map +0 -1
  42. package/lib/CustodyAccount.js.map +0 -1
  43. package/lib/OraclePrice.d.ts.map +0 -1
  44. package/lib/OraclePrice.js.map +0 -1
  45. package/lib/PerpetualsClient.d.ts.map +0 -1
  46. package/lib/PerpetualsClient.js.map +0 -1
  47. package/lib/PoolAccount.d.ts.map +0 -1
  48. package/lib/PoolAccount.js.map +0 -1
  49. package/lib/PositionAccount.d.ts.map +0 -1
  50. package/lib/PositionAccount.js.map +0 -1
  51. package/lib/client/src/CustodyAccount.d.ts +0 -30
  52. package/lib/client/src/CustodyAccount.d.ts.map +0 -1
  53. package/lib/client/src/CustodyAccount.js +0 -64
  54. package/lib/client/src/CustodyAccount.js.map +0 -1
  55. package/lib/client/src/OraclePrice.d.ts +0 -19
  56. package/lib/client/src/OraclePrice.d.ts.map +0 -1
  57. package/lib/client/src/OraclePrice.js +0 -84
  58. package/lib/client/src/OraclePrice.js.map +0 -1
  59. package/lib/client/src/PerpetualsClient.d.ts +0 -1938
  60. package/lib/client/src/PerpetualsClient.d.ts.map +0 -1
  61. package/lib/client/src/PerpetualsClient.js +0 -1043
  62. package/lib/client/src/PerpetualsClient.js.map +0 -1
  63. package/lib/client/src/PoolAccount.d.ts +0 -35
  64. package/lib/client/src/PoolAccount.d.ts.map +0 -1
  65. package/lib/client/src/PoolAccount.js +0 -307
  66. package/lib/client/src/PoolAccount.js.map +0 -1
  67. package/lib/client/src/PositionAccount.d.ts +0 -27
  68. package/lib/client/src/PositionAccount.d.ts.map +0 -1
  69. package/lib/client/src/PositionAccount.js +0 -91
  70. package/lib/client/src/PositionAccount.js.map +0 -1
  71. package/lib/client/src/constants/index.d.ts +0 -12
  72. package/lib/client/src/constants/index.d.ts.map +0 -1
  73. package/lib/client/src/constants/index.js +0 -15
  74. package/lib/client/src/constants/index.js.map +0 -1
  75. package/lib/client/src/index.d.ts +0 -9
  76. package/lib/client/src/index.d.ts.map +0 -1
  77. package/lib/client/src/index.js +0 -26
  78. package/lib/client/src/index.js.map +0 -1
  79. package/lib/client/src/types/index.d.ts +0 -188
  80. package/lib/client/src/types/index.d.ts.map +0 -1
  81. package/lib/client/src/types/index.js +0 -57
  82. package/lib/client/src/types/index.js.map +0 -1
  83. package/lib/client/src/utils/helpers.d.ts +0 -8
  84. package/lib/client/src/utils/helpers.d.ts.map +0 -1
  85. package/lib/client/src/utils/helpers.js +0 -152
  86. package/lib/client/src/utils/helpers.js.map +0 -1
  87. package/lib/constants/index.d.ts.map +0 -1
  88. package/lib/constants/index.js.map +0 -1
  89. package/lib/index.d.ts.map +0 -1
  90. package/lib/index.js.map +0 -1
  91. package/lib/types/index.d.ts.map +0 -1
  92. package/lib/types/index.js.map +0 -1
  93. package/lib/utils/helpers.d.ts +0 -7
  94. package/lib/utils/helpers.d.ts.map +0 -1
  95. package/lib/utils/helpers.js +0 -151
  96. package/lib/utils/helpers.js.map +0 -1
  97. package/src/target/types/limit_order_cpi.js +0 -132
  98. package/src/target/types/limit_order_cpi.ts +0 -259
  99. /package/{src/target/idl/perpetuals.json → lib/Token.d.ts} +0 -0
  100. /package/src/{readme.md → type-rules.md} +0 -0
@@ -14,6 +14,8 @@ import {
14
14
  AccountMeta,
15
15
  Keypair,
16
16
  SYSVAR_RENT_PUBKEY,
17
+ Commitment,
18
+ LAMPORTS_PER_SOL,
17
19
  } from "@solana/web3.js";
18
20
  import {
19
21
  getAccount,
@@ -22,22 +24,26 @@ import {
22
24
  createCloseAccountInstruction,
23
25
  createSyncNativeInstruction,
24
26
  TOKEN_PROGRAM_ID,
27
+ NATIVE_MINT,
25
28
  } from "@solana/spl-token";
26
29
 
27
30
  import { sha256 } from "js-sha256";
28
31
  import { encode } from "bs58";
29
32
  import { PoolAccount } from "./PoolAccount";
30
33
  import { PositionAccount } from "./PositionAccount";
31
- import { BorrowRateParams, Custody, Fees, OracleParams, Permissions, Position, PositionSide, PricingParams, TokenRatios, isVariant } from "./types";
34
+ import { AumCalcMode, BorrowRateParams, Custody, Fees, OracleParams, Permissions, Position, PositionSide, PricingParams, Side, TokenRatios, isVariant } from "./types";
32
35
  import { OraclePrice } from "./OraclePrice";
33
36
  import { CustodyAccount } from "./CustodyAccount";
34
- import { Perpetuals } from "./target/types/perpetuals";
35
- import {IDL} from './target/types/perpetuals';
37
+ import { Perpetuals } from "./idl/perpetuals";
38
+ import { IDL } from './idl/perpetuals';
39
+ import { sendTransaction } from "./utils/rpc";
40
+ import { PoolConfig } from "./PoolConfig";
41
+ import { checkIfAccountExists } from "./utils";
36
42
 
37
43
 
38
44
  /* USEAGE
39
45
 
40
- UI ---
46
+ UI -----
41
47
  provider = from phatom
42
48
 
43
49
  client = new PerpetualsClient(provider, user.pubkey , programId);
@@ -56,6 +62,13 @@ process.env["ANCHOR_WALLET"] = adminKeyPath;
56
62
  client = new PerpetualsClient(provider, DEFAULT_PERPS_USER.pubkey , programId);
57
63
 
58
64
  */
65
+
66
+ export type PerpClientOptions = {
67
+ postSendTxCallback?: ({ txid }: { txid: string }) => void;
68
+ prioritizationFee?: number;
69
+ txConfirmationCommitment?: Commitment;
70
+ };
71
+
59
72
  export class PerpetualsClient {
60
73
  provider: AnchorProvider;
61
74
  program: Program<Perpetuals>;
@@ -67,7 +80,11 @@ export class PerpetualsClient {
67
80
  authority: { publicKey: PublicKey; bump: number };
68
81
  perpetuals: { publicKey: PublicKey; bump: number };
69
82
 
70
- constructor(provider: AnchorProvider, programId: PublicKey) {
83
+ private postSendTxCallback?: ({ txid }) => void;
84
+ private prioritizationFee: number;
85
+ private txConfirmationCommitment: Commitment;
86
+
87
+ constructor(provider: AnchorProvider, programId: PublicKey, opts: PerpClientOptions) {
71
88
  // this.provider = AnchorProvider.local(clusterUrl, {
72
89
  // commitment: "confirmed",
73
90
  // preflightCommitment: "confirmed",
@@ -80,27 +97,32 @@ export class PerpetualsClient {
80
97
  // const idl = JSON.parse( fs.readFileSync("./target/idl/perpetuals.json", "utf8"));
81
98
  // const idl = JSON.parse(IDL);
82
99
  // const program = new anchor.Program(idl, programId, provider);
83
- this.program = new Program(IDL, programId);
100
+ this.program = new Program(IDL, programId);
101
+ this.programId = programId;
84
102
  //this.program = workspace.Perpetuals as Program<Perpetuals>;
85
- console.log("client constructor programID : ",this.program.programId.toBase58());
103
+ console.log("client constructor programID : ", this.program.programId.toBase58());
86
104
 
87
105
  // this.admin = Keypair.fromSecretKey(
88
106
  // new Uint8Array(JSON.parse(readFileSync(adminKey).toString()))
89
107
  // );
90
108
 
91
- this.admin = this.provider.wallet.publicKey;
92
- console.log("admin:",this.admin.toBase58())
109
+ this.admin = this.provider.wallet.publicKey;
110
+ console.log("admin:", this.admin.toBase58())
93
111
 
94
112
  this.multisig = this.findProgramAddress("multisig");
95
113
  this.authority = this.findProgramAddress("transfer_authority");
96
114
  this.perpetuals = this.findProgramAddress("perpetuals");
97
115
 
116
+ this.prioritizationFee = opts?.prioritizationFee || 0;
117
+ this.postSendTxCallback = opts?.postSendTxCallback;
118
+ this.txConfirmationCommitment = opts?.txConfirmationCommitment ?? 'processed'
119
+
98
120
  BN.prototype.toJSON = function () {
99
121
  return this.toString(10);
100
122
  };
101
123
  }
102
124
 
103
- findProgramAddress = (label: string, extraSeeds :any = null) => {
125
+ findProgramAddress = (label: string, extraSeeds: any = null) => {
104
126
  let seeds = [Buffer.from(utils.bytes.utf8.encode(label))];
105
127
  if (extraSeeds) {
106
128
  for (let extraSeed of extraSeeds) {
@@ -117,7 +139,7 @@ export class PerpetualsClient {
117
139
  return { publicKey: res[0], bump: res[1] };
118
140
  };
119
141
 
120
- adjustTokenRatios = (ratios : TokenRatios[]) => {
142
+ adjustTokenRatios = (ratios: TokenRatios[]) => {
121
143
  if (ratios.length == 0) {
122
144
  return ratios;
123
145
  }
@@ -145,7 +167,7 @@ export class PerpetualsClient {
145
167
  };
146
168
 
147
169
  getPool = async (name: string) => {
148
- console.log("pool:",this.getPoolKey(name).toBase58())
170
+ console.log("pool:", this.getPoolKey(name).toBase58())
149
171
  return this.program.account.pool.fetch(this.getPoolKey(name));
150
172
  };
151
173
 
@@ -189,7 +211,7 @@ export class PerpetualsClient {
189
211
  };
190
212
 
191
213
  getCustody = async (poolName: string, tokenMint: PublicKey) => {
192
- console.log("custody key :",this.getCustodyKey(poolName, tokenMint).toBase58());
214
+ console.log("custody key :", this.getCustodyKey(poolName, tokenMint).toBase58());
193
215
  return this.program.account.custody.fetch(
194
216
  this.getCustodyKey(poolName, tokenMint)
195
217
  );
@@ -197,7 +219,7 @@ export class PerpetualsClient {
197
219
 
198
220
  getCustodies = async (poolName: string) => {
199
221
  //return this.program.account.custody.all();
200
- let pool = await this.getPool(poolName);
222
+ let pool = await this.getPool(poolName);
201
223
  return this.program.account.custody.fetchMultiple(
202
224
  pool.custodies
203
225
  );
@@ -205,7 +227,7 @@ export class PerpetualsClient {
205
227
 
206
228
  getCustodyMetas = async (poolName: string) => {
207
229
  let pool = await this.getPool(poolName);
208
- let custodies :any = await this.program.account.custody.fetchMultiple(
230
+ let custodies: any = await this.program.account.custody.fetchMultiple(
209
231
  pool.custodies
210
232
  );
211
233
  let custodyMetas = [];
@@ -246,7 +268,7 @@ export class PerpetualsClient {
246
268
  ]).publicKey;
247
269
  };
248
270
 
249
- getPosition = async (postionKey : PublicKey) => {
271
+ getPosition = async (postionKey: PublicKey) => {
250
272
  return this.program.account.position.fetch(postionKey);
251
273
  };
252
274
 
@@ -433,55 +455,55 @@ export class PerpetualsClient {
433
455
  poolName: string,
434
456
  tokenMint: PublicKey,
435
457
  isStable: boolean,
436
- oracle : OracleParams,
458
+ oracle: OracleParams,
437
459
  pricing: PricingParams,
438
- permissions : Permissions,
439
- fees : Fees,
440
- borrowRate : BorrowRateParams,
441
- ratios : TokenRatios[]
460
+ permissions: Permissions,
461
+ fees: Fees,
462
+ borrowRate: BorrowRateParams,
463
+ ratios: TokenRatios[]
442
464
  ) => {
443
- console.log("CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
444
- console.log("getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
465
+ console.log("CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
466
+ console.log("getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
445
467
  try {
446
- const trx_id = await this.program.methods
447
- // @ts-ignore
448
- .addCustody({
449
- isStable,
450
- oracle,
451
- pricing,
452
- permissions,
453
- fees,
454
- borrowRate,
455
- ratios,
456
- })
457
- .accounts({
458
- admin: this.admin,
459
- multisig: this.multisig.publicKey,
460
- transferAuthority: this.authority.publicKey,
461
- perpetuals: this.perpetuals.publicKey,
462
- pool: this.getPoolKey(poolName),
463
- custody: this.getCustodyKey(poolName, tokenMint),
464
- custodyTokenAccount: this.getCustodyTokenAccountKey(
465
- poolName,
466
- tokenMint
467
- ),
468
- custodyTokenMint: tokenMint,
469
- systemProgram: SystemProgram.programId,
470
- tokenProgram: TOKEN_PROGRAM_ID,
471
- rent: SYSVAR_RENT_PUBKEY,
472
- })
473
- // .signers([this.admin])
474
- .rpc()
475
- .catch((err) => {
476
- console.error(err);
477
- throw err;
478
- });
468
+ const trx_id = await this.program.methods
469
+ // @ts-ignore
470
+ .addCustody({
471
+ isStable,
472
+ oracle,
473
+ pricing,
474
+ permissions,
475
+ fees,
476
+ borrowRate,
477
+ ratios,
478
+ })
479
+ .accounts({
480
+ admin: this.admin,
481
+ multisig: this.multisig.publicKey,
482
+ transferAuthority: this.authority.publicKey,
483
+ perpetuals: this.perpetuals.publicKey,
484
+ pool: this.getPoolKey(poolName),
485
+ custody: this.getCustodyKey(poolName, tokenMint),
486
+ custodyTokenAccount: this.getCustodyTokenAccountKey(
487
+ poolName,
488
+ tokenMint
489
+ ),
490
+ custodyTokenMint: tokenMint,
491
+ systemProgram: SystemProgram.programId,
492
+ tokenProgram: TOKEN_PROGRAM_ID,
493
+ rent: SYSVAR_RENT_PUBKEY,
494
+ })
495
+ // .signers([this.admin])
496
+ .rpc()
497
+ .catch((err) => {
498
+ console.error(err);
499
+ throw err;
500
+ });
479
501
 
480
502
  console.log("trx_id:", `https://explorer.solana.com/tx/${trx_id}?cluster=devnet`)
481
503
  } catch (error) {
482
- console.log("cli error :",error);
504
+ console.log("cli error :", error);
483
505
  }
484
-
506
+
485
507
 
486
508
  };
487
509
 
@@ -489,18 +511,18 @@ export class PerpetualsClient {
489
511
  poolName: string,
490
512
  tokenMint: PublicKey,
491
513
  isStable: boolean,
492
- oracle : OracleParams,
514
+ oracle: OracleParams,
493
515
  pricing: PricingParams,
494
- permissions : Permissions,
495
- fees : Fees,
496
- borrowRate : BorrowRateParams,
497
- ratios : TokenRatios[]
516
+ permissions: Permissions,
517
+ fees: Fees,
518
+ borrowRate: BorrowRateParams,
519
+ ratios: TokenRatios[]
498
520
  ) => {
499
- console.log("CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
500
- console.log("getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
521
+ console.log("CustodyKey", this.getCustodyKey(poolName, tokenMint).toBase58())
522
+ console.log("getCustodyTokenAccountKey", this.getCustodyTokenAccountKey(poolName, tokenMint).toBase58())
501
523
 
502
- const trx_id = await this.program.methods
503
- //@ts-ignore
524
+ const trx_id = await this.program.methods
525
+ //@ts-ignore
504
526
  .testingEditCustody({
505
527
  isStable,
506
528
  oracle,
@@ -532,10 +554,10 @@ export class PerpetualsClient {
532
554
  console.error(err);
533
555
  throw err;
534
556
  });
535
- console.log("trx_id:", `https://explorer.solana.com/tx/${trx_id}?cluster=devnet`)
557
+ console.log("trx_id:", `https://explorer.solana.com/tx/${trx_id}?cluster=devnet`)
536
558
  };
537
559
 
538
- removeCustody = async (poolName: string, tokenMint: PublicKey, ratios:TokenRatios[]) => {
560
+ removeCustody = async (poolName: string, tokenMint: PublicKey, ratios: TokenRatios[]) => {
539
561
  await this.program.methods
540
562
  .removeCustody({ ratios })
541
563
  .accounts({
@@ -646,7 +668,7 @@ export class PerpetualsClient {
646
668
  amount: BN
647
669
  ) => {
648
670
  return await this.program.methods
649
- .getAddLiquidityAmountAndFee({
671
+ .getAddLiquidityAmountAndFee({
650
672
  amountIn: amount,
651
673
  })
652
674
  .accounts({
@@ -667,8 +689,6 @@ export class PerpetualsClient {
667
689
  });
668
690
  };
669
691
 
670
-
671
-
672
692
  getRemoveLiquidityAmountAndFee = async (
673
693
  poolName: string,
674
694
  tokenMint: PublicKey,
@@ -699,23 +719,23 @@ export class PerpetualsClient {
699
719
  getEntryPriceAndFee = async (
700
720
  poolName: string,
701
721
  tokenMint: PublicKey,
702
- collateral: BN,
703
- size: BN,
722
+ collateral: BN,
723
+ size: BN,
704
724
  side: PositionSide
705
725
  ) => {
706
726
  console.log("perps: ", this.perpetuals.publicKey.toBase58())
707
727
 
708
728
  console.log("poolKey: ", this.getPoolKey(poolName).toBase58())
709
- console.log("custody key : ",this.getCustodyKey(poolName, tokenMint).toBase58());
710
- console.log("orcalve: ", (await this.getCustodyOracleAccountKey(poolName,tokenMint)).toBase58())
729
+ console.log("custody key : ", this.getCustodyKey(poolName, tokenMint).toBase58());
730
+ console.log("orcalve: ", (await this.getCustodyOracleAccountKey(poolName, tokenMint)).toBase58())
711
731
 
712
732
  //@ts-ignore
713
733
  return await this.program.methods
714
- //@ts-ignore
715
- .getEntryPriceAndFee({
734
+ //@ts-ignore
735
+ .getEntryPriceAndFee({
716
736
  collateral,
717
737
  size,
718
- side: side == "long" ? { long: {} } : { short: {} },
738
+ side: side == "long" ? { long: {} } : { short: {} },
719
739
  })
720
740
  .accounts({
721
741
  // signer: this.provider.wallet.publicKey,
@@ -886,7 +906,7 @@ export class PerpetualsClient {
886
906
  side: PositionSide
887
907
  ) => {
888
908
  const pos = this.getPositionKey(wallet, poolName, tokenMint, side);
889
- console.log("pos:",pos.toBase58())
909
+ console.log("pos:", pos.toBase58())
890
910
  return await this.program.methods
891
911
  .getPnl({})
892
912
  .accounts({
@@ -914,7 +934,7 @@ export class PerpetualsClient {
914
934
  side: PositionSide
915
935
  ) => {
916
936
  const pos = this.getPositionKey(wallet, poolName, tokenMint, side);
917
- console.log("pos:",pos.toBase58())
937
+ console.log("pos:", pos.toBase58())
918
938
  return await this.program.methods
919
939
  .getPnl({})
920
940
  .accounts({
@@ -935,33 +955,33 @@ export class PerpetualsClient {
935
955
  };
936
956
 
937
957
 
938
- getPnl2 = (
939
- postionKey : PublicKey,
958
+ getPnl2 = (
959
+ postionKey: PublicKey,
940
960
  postionData: Position,
941
- tokenPrice : OraclePrice,
942
- tokenEmaPrice : OraclePrice,
943
- custodyAccount : CustodyAccount,
944
- poolAccount : PoolAccount,
945
- currentTime : BN
961
+ tokenPrice: OraclePrice,
962
+ tokenEmaPrice: OraclePrice,
963
+ custodyAccount: CustodyAccount,
964
+ poolAccount: PoolAccount,
965
+ currentTime: BN
946
966
  ) => {
947
-
967
+
948
968
  const positionAccount = PositionAccount.from(postionKey, postionData);
949
969
  // console.log("positionAccount:",positionAccount);
950
970
  // console.log("side :", postionData.side, (isVariant(postionData.side, 'long')))
951
971
 
952
- let {profit, loss, exitFee} = poolAccount.getPnlUsd(
972
+ let { profit, loss, exitFee } = poolAccount.getPnlUsd(
953
973
  positionAccount,
954
974
  tokenPrice,
955
975
  tokenEmaPrice,
956
976
  custodyAccount,
957
977
  currentTime,
958
978
  false,
959
- );
979
+ );
960
980
 
961
- return {
962
- profit,
963
- loss
964
- }
981
+ return {
982
+ profit,
983
+ loss
984
+ }
965
985
 
966
986
  }
967
987
 
@@ -996,7 +1016,7 @@ export class PerpetualsClient {
996
1016
  });
997
1017
  };
998
1018
 
999
- getAum = async (poolName: string) => {
1019
+ getAumView = async (poolName: string) => {
1000
1020
  return await this.program.methods
1001
1021
  .getAssetsUnderManagement({})
1002
1022
  .accounts({
@@ -1010,4 +1030,625 @@ export class PerpetualsClient {
1010
1030
  throw err;
1011
1031
  });
1012
1032
  };
1033
+
1034
+ getAumTrx = async (poolName: string) => {
1035
+ return await this.program.methods
1036
+ .getAssetsUnderManagement({})
1037
+ .accounts({
1038
+ perpetuals: this.perpetuals.publicKey,
1039
+ pool: this.getPoolKey(poolName),
1040
+ })
1041
+ .remainingAccounts(await this.getCustodyMetas(poolName))
1042
+ .rpc()
1043
+ .catch((err) => {
1044
+ console.error(err);
1045
+ throw err;
1046
+ });
1047
+ };
1048
+
1049
+ getAumSdk = (
1050
+ poolAccount: PoolAccount,
1051
+ token_prices: OraclePrice[],
1052
+ token_ema_prices: OraclePrice[],
1053
+ custodies: CustodyAccount[],
1054
+ aum_calc_mode: AumCalcMode,
1055
+ currentTime: BN
1056
+ ) => {
1057
+ // console.log("poolAccount:",poolAccount);
1058
+
1059
+ return poolAccount.getAssetsUnderManagementUsd(
1060
+ token_prices,
1061
+ token_ema_prices,
1062
+ custodies,
1063
+ aum_calc_mode,
1064
+ currentTime
1065
+ );
1066
+ };
1067
+
1068
+ // TODO: handle SOL wrapping to WSOL and create a ATA - DONE
1069
+ // TODO: Balance checks - DONE
1070
+ // TODO: ATA check - else create - DONE
1071
+ // TODO: for close Accounts - NOT NEEDED
1072
+ openPosition = async (
1073
+ payTokenSymbol: string,
1074
+ price: BN,
1075
+ collateral: BN,
1076
+ size: BN,
1077
+ side: Side,
1078
+ slippagePercentage: number,
1079
+ poolConfig: PoolConfig
1080
+ ): Promise<TransactionInstruction[]> => {
1081
+
1082
+ console.log("open position :::", payTokenSymbol, poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey.toBase58());
1083
+
1084
+ const slippageMultiplier = isVariant(side, 'long') ? -1 : 1;
1085
+ const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
1086
+
1087
+ let publicKey = this.provider.wallet.publicKey;
1088
+ const payTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey))!;
1089
+
1090
+ let userCustodyTokenAccount = await getAssociatedTokenAddress(
1091
+ poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey,
1092
+ publicKey
1093
+ );
1094
+
1095
+ const instructions = [];
1096
+ try {
1097
+
1098
+ if (payTokenSymbol == 'SOL') {
1099
+ console.log("payTokenSymbol === sol", payTokenSymbol);
1100
+ const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
1101
+ NATIVE_MINT,
1102
+ publicKey
1103
+ );
1104
+ const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
1105
+ if (!wsolATAExist) {
1106
+ console.log("wsol ata does not exist");
1107
+ instructions.push(
1108
+ createAssociatedTokenAccountInstruction(
1109
+ publicKey,
1110
+ wsolAssociatedTokenAccount,
1111
+ publicKey,
1112
+ NATIVE_MINT
1113
+ )
1114
+ );
1115
+ }
1116
+
1117
+ // get balance of WSOL associated token account
1118
+ const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
1119
+ if (wsolBalance.lt(collateral)) {
1120
+ // console.log("WSOL balance insufficient");
1121
+ // so Convert SOL to WSOL
1122
+ let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
1123
+ const totalSolBal = unWrappedSolBalance.add(wsolBalance);
1124
+ if (totalSolBal.lt(collateral)) {
1125
+ throw "Insufficient SOL Funds"
1126
+ }
1127
+
1128
+ let conversionAmt = collateral.sub(wsolBalance);
1129
+ instructions.push(
1130
+ SystemProgram.transfer({
1131
+ fromPubkey: publicKey,
1132
+ toPubkey: wsolAssociatedTokenAccount,
1133
+ lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER
1134
+ }),
1135
+ createSyncNativeInstruction(wsolAssociatedTokenAccount)
1136
+ );
1137
+ }
1138
+ } else {
1139
+ if (!(await checkIfAccountExists(userCustodyTokenAccount, this.provider.connection))) {
1140
+ throw "Insufficient Funds , token Account doesn't exist"
1141
+ }
1142
+ const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userCustodyTokenAccount)).value.amount);
1143
+ if (tokenAccountBalance.lt(collateral)) {
1144
+ throw "Insufficient Funds"
1145
+ }
1146
+ }
1147
+
1148
+ // replace with getPositionKey()
1149
+ let positionAccount = PublicKey.findProgramAddressSync(
1150
+ [
1151
+ Buffer.from("position"),
1152
+ publicKey.toBuffer(),
1153
+ poolConfig.poolAddress.toBuffer(),
1154
+ payTokenCustody.custodyAccount.toBuffer(),
1155
+ isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
1156
+ ],
1157
+ this.programId
1158
+ )[0];
1159
+
1160
+ const params: any = {
1161
+ price: priceAfterSlippage,
1162
+ collateral,
1163
+ size,
1164
+ side,
1165
+ };
1166
+
1167
+ let instruction = await this.program.methods
1168
+ .openPosition(params)
1169
+ .accounts({
1170
+ owner: publicKey,
1171
+ fundingAccount: userCustodyTokenAccount,
1172
+ transferAuthority: poolConfig.transferAuthority,
1173
+ perpetuals: poolConfig.perpetuals,
1174
+ pool: poolConfig.poolAddress,
1175
+ position: positionAccount,
1176
+ custody: payTokenCustody.custodyAccount,
1177
+ custodyOracleAccount:
1178
+ payTokenCustody.oracleAddress,
1179
+ custodyTokenAccount:
1180
+ payTokenCustody.tokenAccount,
1181
+ systemProgram: SystemProgram.programId,
1182
+ tokenProgram: TOKEN_PROGRAM_ID,
1183
+ }).instruction()
1184
+ instructions.push(instruction);
1185
+
1186
+ } catch (error) {
1187
+ console.log("perpClient openPosition error:", error)
1188
+ }
1189
+ return instructions;
1190
+ }
1191
+
1192
+ // TODO: handle SOL wrapping to WSOL and create a ATA - NOT NEEDED
1193
+ // TODO : Balance checks - NOT NEEDED
1194
+ // TODO: ATA check - else create - DONE
1195
+ // TODO: for close Accounts - DONE BY ANCHOR
1196
+ closePosition = async (
1197
+ receivingTokenSymbol: string,
1198
+ price: BN,
1199
+ side: Side,
1200
+ slippagePercentage: number,
1201
+ poolConfig: PoolConfig
1202
+ ): Promise<TransactionInstruction[]> => {
1203
+
1204
+ console.log("close position :::", receivingTokenSymbol, poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey.toBase58());
1205
+
1206
+ const slippageMultiplier = isVariant(side, 'long') ? -1 : 1;
1207
+ const priceAfterSlippage = price.mul(new BN((100 - (slippagePercentage * slippageMultiplier)) * 100)).div(new BN(100 * 100))
1208
+
1209
+ let publicKey = this.provider.wallet.publicKey;
1210
+
1211
+ let userReceivingTokenAccount = await getAssociatedTokenAddress(
1212
+ poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey,
1213
+ publicKey
1214
+ );
1215
+ const instructions = [];
1216
+ try {
1217
+
1218
+ if (!(await checkIfAccountExists(userReceivingTokenAccount, this.provider.connection))) {
1219
+ instructions.push(
1220
+ createAssociatedTokenAccountInstruction(
1221
+ publicKey,
1222
+ userReceivingTokenAccount,
1223
+ publicKey,
1224
+ poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey
1225
+ )
1226
+ );
1227
+ }
1228
+
1229
+ const receivingTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey))!;
1230
+
1231
+ // replace with getPositionKey
1232
+ let positionAccount = PublicKey.findProgramAddressSync(
1233
+ [
1234
+ Buffer.from("position"),
1235
+ publicKey.toBuffer(),
1236
+ poolConfig.poolAddress.toBuffer(),
1237
+ receivingTokenCustody.custodyAccount.toBuffer(),
1238
+ isVariant(side, 'long') ? Buffer.from([1]) : Buffer.from([2]),
1239
+ ],
1240
+ this.programId
1241
+ )[0];
1242
+
1243
+ console.log("positionAccount:", positionAccount.toBase58())
1244
+ const params: any = {
1245
+ price: priceAfterSlippage,
1246
+ };
1247
+
1248
+ let instruction = await this.program.methods
1249
+ .closePosition(params)
1250
+ .accounts({
1251
+ owner: publicKey,
1252
+ receivingAccount: userReceivingTokenAccount,
1253
+ transferAuthority: poolConfig.transferAuthority,
1254
+ perpetuals: poolConfig.perpetuals,
1255
+ pool: poolConfig.poolAddress,
1256
+ position: positionAccount,
1257
+ custody: receivingTokenCustody.custodyAccount,
1258
+ custodyOracleAccount:
1259
+ receivingTokenCustody.oracleAddress,
1260
+ custodyTokenAccount:
1261
+ receivingTokenCustody.tokenAccount,
1262
+ tokenProgram: TOKEN_PROGRAM_ID,
1263
+ }).instruction();
1264
+ instructions.push(instruction)
1265
+ } catch (error) {
1266
+ console.error("perpclient closePosition error:", error);
1267
+ }
1268
+
1269
+ return instructions;
1270
+ }
1271
+
1272
+ // TODO: ATA check - else create - DONE
1273
+ // TODO: handle SOL wrapping to WSOL and create a ATA - DONE
1274
+ // TODO : Balance checks - NOT NEEDED
1275
+ // TODO: for close Accounts - DONE BY ANCHOR
1276
+ swap = async (
1277
+ receivingTokenSymbol: string,
1278
+ dispensingTokenSymbol: string,
1279
+ amountIn: BN,
1280
+ minAmountOut: BN,
1281
+ poolConfig: PoolConfig
1282
+ ): Promise<TransactionInstruction[]> => {
1283
+
1284
+ const receivingTokenCustody = poolConfig.custodies.find(
1285
+ (i) => i.mintKey.toBase58() === poolConfig.getTokenFromSymbol(receivingTokenSymbol).mintKey.toBase58()
1286
+ );
1287
+ if (!receivingTokenCustody) {
1288
+ throw "receivingTokenCustody not found";
1289
+ }
1290
+ const dispensingTokenCustody = poolConfig.custodies.find(
1291
+ (i) => i.mintKey.toBase58() === poolConfig.getTokenFromSymbol(dispensingTokenSymbol).mintKey.toBase58()
1292
+ );
1293
+ if (!dispensingTokenCustody) {
1294
+ throw "dispensingTokenCustody not found";
1295
+ }
1296
+ let publicKey = this.provider.wallet.publicKey;
1297
+
1298
+
1299
+ const instructions = [];
1300
+ try {
1301
+ let receivingTokenAccount = await getAssociatedTokenAddress(
1302
+ receivingTokenCustody.mintKey,
1303
+ publicKey
1304
+ );
1305
+ if (!(await checkIfAccountExists(receivingTokenAccount, this.provider.connection))) {
1306
+ instructions.push(
1307
+ createAssociatedTokenAccountInstruction(
1308
+ publicKey,
1309
+ receivingTokenAccount,
1310
+ publicKey,
1311
+ receivingTokenCustody.mintKey
1312
+ )
1313
+ );
1314
+ }
1315
+
1316
+ let dispensingCustodyTokenAccount = await getAssociatedTokenAddress(
1317
+ dispensingTokenCustody.mintKey,
1318
+ publicKey
1319
+ );
1320
+ if (dispensingTokenSymbol == 'SOL') {
1321
+ console.log("dispensingTokenSymbol === sol", dispensingTokenSymbol);
1322
+ const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
1323
+ NATIVE_MINT,
1324
+ publicKey
1325
+ );
1326
+ const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
1327
+ if (!wsolATAExist) {
1328
+ console.log("wsol ata does not exist");
1329
+ instructions.push(
1330
+ createAssociatedTokenAccountInstruction(
1331
+ publicKey,
1332
+ wsolAssociatedTokenAccount,
1333
+ publicKey,
1334
+ NATIVE_MINT
1335
+ )
1336
+ );
1337
+ }
1338
+
1339
+ // get balance of WSOL associated token account
1340
+ const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
1341
+ if (wsolBalance.lt(amountIn)) {
1342
+ // console.log("WSOL balance insufficient");
1343
+ // so Convert SOL to WSOL
1344
+ let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
1345
+ const totalSolBal = unWrappedSolBalance.add(wsolBalance);
1346
+ if (totalSolBal.lt(amountIn)) {
1347
+ throw "Insufficient SOL Funds"
1348
+ }
1349
+
1350
+ let conversionAmt = amountIn.sub(wsolBalance);
1351
+ instructions.push(
1352
+ SystemProgram.transfer({
1353
+ fromPubkey: publicKey,
1354
+ toPubkey: wsolAssociatedTokenAccount,
1355
+ lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER ?
1356
+ }),
1357
+ createSyncNativeInstruction(wsolAssociatedTokenAccount)
1358
+ );
1359
+ }
1360
+ } else {
1361
+ if (!(await checkIfAccountExists(dispensingCustodyTokenAccount, this.provider.connection))) {
1362
+ throw "Insufficient Funds , Token Account doesn't exist"
1363
+ }
1364
+ const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(dispensingCustodyTokenAccount)).value.amount);
1365
+ if (tokenAccountBalance.lt(amountIn)) {
1366
+ throw "Insufficient Funds"
1367
+ }
1368
+ }
1369
+
1370
+ const params = {
1371
+ amountIn,
1372
+ minAmountOut,
1373
+ };
1374
+ let inx = await this.program.methods
1375
+ .swap(params)
1376
+ .accounts({
1377
+ owner: publicKey,
1378
+ fundingAccount: dispensingCustodyTokenAccount,
1379
+ receivingAccount: receivingTokenAccount,
1380
+ transferAuthority: poolConfig.transferAuthority,
1381
+ perpetuals: poolConfig.perpetuals,
1382
+ pool: poolConfig.poolAddress,
1383
+
1384
+ receivingCustody: dispensingTokenCustody.custodyAccount,
1385
+ receivingCustodyOracleAccount: dispensingTokenCustody.oracleAddress,
1386
+ receivingCustodyTokenAccount: dispensingTokenCustody.tokenAccount,
1387
+
1388
+ dispensingCustody: receivingTokenCustody.custodyAccount,
1389
+ dispensingCustodyOracleAccount: receivingTokenCustody.oracleAddress,
1390
+ dispensingCustodyTokenAccount: receivingTokenCustody.tokenAccount,
1391
+ tokenProgram: TOKEN_PROGRAM_ID,
1392
+ })
1393
+ .instruction();
1394
+
1395
+ instructions.push(inx)
1396
+ } catch (err) {
1397
+ console.log("perpClient Swap error:: ", err);
1398
+ throw err;
1399
+ }
1400
+
1401
+ return instructions;
1402
+ }
1403
+
1404
+ // TODO: handle SOL wrapping to WSOL and create a ATA - DONE
1405
+ // TODO :Balance checks - DONE
1406
+ // TODO: ATA check - else create - DONE
1407
+ // TODO: for close Accounts - NOT NEEDED
1408
+ addLiquidity = async (
1409
+ payTokenSymbol: string,
1410
+ tokenAmountIn: BN,
1411
+ minLpAmountOut: BN, // give this value based on slippage
1412
+ poolConfig: PoolConfig
1413
+ ): Promise<TransactionInstruction[]> => {
1414
+
1415
+ const payTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(payTokenSymbol).mintKey))!;
1416
+ if (!payTokenCustody) {
1417
+ throw "payTokenCustody not found";
1418
+ }
1419
+ let publicKey = this.provider.wallet.publicKey;
1420
+
1421
+ const instructions = [];
1422
+ try {
1423
+
1424
+ let userPayingTokenAccount = await getAssociatedTokenAddress(
1425
+ payTokenCustody.mintKey,
1426
+ publicKey
1427
+ );
1428
+
1429
+ let lpTokenAccount = await getAssociatedTokenAddress(
1430
+ poolConfig.lpTokenMint,
1431
+ publicKey
1432
+ );
1433
+
1434
+ let custodyAccountMetas = [];
1435
+ let custodyOracleAccountMetas = [];
1436
+ for (const custody of poolConfig.custodies) {
1437
+ custodyAccountMetas.push({
1438
+ pubkey: custody.custodyAccount,
1439
+ isSigner: false,
1440
+ isWritable: false,
1441
+ });
1442
+
1443
+ custodyOracleAccountMetas.push({
1444
+ pubkey: custody.oracleAddress,
1445
+ isSigner: false,
1446
+ isWritable: false,
1447
+ });
1448
+ }
1449
+
1450
+ if (!(await checkIfAccountExists(lpTokenAccount, this.provider.connection))) {
1451
+ instructions.push(
1452
+ createAssociatedTokenAccountInstruction(
1453
+ publicKey,
1454
+ lpTokenAccount,
1455
+ publicKey,
1456
+ poolConfig.lpTokenMint
1457
+ )
1458
+ );
1459
+ }
1460
+
1461
+ if (payTokenSymbol == 'SOL') {
1462
+ console.log("payTokenSymbol === sol", payTokenSymbol);
1463
+ const wsolAssociatedTokenAccount = await getAssociatedTokenAddress(
1464
+ NATIVE_MINT,
1465
+ publicKey
1466
+ );
1467
+
1468
+ const wsolATAExist = await checkIfAccountExists(wsolAssociatedTokenAccount, this.provider.connection)
1469
+ if (!wsolATAExist) {
1470
+ console.log("wsol ata does not exist");
1471
+ instructions.push(
1472
+ createAssociatedTokenAccountInstruction(
1473
+ publicKey,
1474
+ wsolAssociatedTokenAccount,
1475
+ publicKey,
1476
+ NATIVE_MINT
1477
+ )
1478
+ );
1479
+ }
1480
+
1481
+ // get balance of WSOL associated token account
1482
+ const wsolBalance = new BN(wsolATAExist ? (await this.provider.connection.getTokenAccountBalance(wsolAssociatedTokenAccount)).value.amount : 0);
1483
+ if (wsolBalance.lt(tokenAmountIn)) {
1484
+ // console.log("WSOL balance insufficient");
1485
+ // so Convert SOL to WSOL
1486
+ let unWrappedSolBalance = new BN(await this.provider.connection.getBalance(publicKey));
1487
+ const totalSolBal = unWrappedSolBalance.add(wsolBalance);
1488
+ if (totalSolBal.lt(tokenAmountIn)) {
1489
+ throw "Insufficient SOL Funds"
1490
+ }
1491
+
1492
+ let conversionAmt = tokenAmountIn.sub(wsolBalance);
1493
+ instructions.push(
1494
+ SystemProgram.transfer({
1495
+ fromPubkey: publicKey,
1496
+ toPubkey: wsolAssociatedTokenAccount,
1497
+ lamports: conversionAmt.toNumber(), // IS IT SAFE TO PUT AS NUMBER
1498
+ }),
1499
+ createSyncNativeInstruction(wsolAssociatedTokenAccount)
1500
+ );
1501
+ }
1502
+ } else {
1503
+ if (!(await checkIfAccountExists(userPayingTokenAccount, this.provider.connection))) {
1504
+ throw "Insufficient Funds , token Account doesn't exist"
1505
+ }
1506
+ const tokenAccountBalance = new BN((await this.provider.connection.getTokenAccountBalance(userPayingTokenAccount)).value.amount);
1507
+ if (tokenAccountBalance.lt(tokenAmountIn)) {
1508
+ throw "Insufficient Funds"
1509
+ }
1510
+ }
1511
+
1512
+ console.log("in add liq", tokenAmountIn);
1513
+
1514
+ let inx = await this.program.methods
1515
+ .addLiquidity({
1516
+ amountIn: tokenAmountIn,
1517
+ minLpAmountOut
1518
+ })
1519
+ .accounts({
1520
+ owner: publicKey,
1521
+ fundingAccount: userPayingTokenAccount, // user token account for custody token account
1522
+ lpTokenAccount,
1523
+ transferAuthority: poolConfig.transferAuthority,
1524
+ perpetuals: poolConfig.perpetuals,
1525
+ pool: poolConfig.poolAddress,
1526
+ custody: payTokenCustody.custodyAccount,
1527
+ custodyOracleAccount: payTokenCustody.oracleAddress,
1528
+ custodyTokenAccount: payTokenCustody.tokenAccount,
1529
+ lpTokenMint: poolConfig.lpTokenMint,
1530
+ tokenProgram: TOKEN_PROGRAM_ID,
1531
+ })
1532
+ .remainingAccounts([...custodyAccountMetas, ...custodyOracleAccountMetas])
1533
+ .instruction();
1534
+
1535
+ instructions.push(inx)
1536
+ } catch (err) {
1537
+ console.log("perpClient addLiquidity error:: ", err);
1538
+ throw err;
1539
+ }
1540
+
1541
+ return instructions;
1542
+ }
1543
+ // TODO: handle SOL wrapping to WSOL and create a ATA - NOT NEEDED
1544
+ // TODO :Balance checks - DONE
1545
+ // TODO: ATA check - else create - DONE
1546
+ // TODO: for LP close Accounts - DONE
1547
+ removeLiquidity = async (
1548
+ recieveTokenSymbol: string,
1549
+ liquidityAmountIn: BN,
1550
+ minTokenAmountOut: BN, // give this value based on slippage
1551
+ poolConfig: PoolConfig,
1552
+ closeLpATA = false
1553
+ ): Promise<TransactionInstruction[]> => {
1554
+
1555
+ const recieveTokenCustody = poolConfig.custodies.find(i => i.mintKey.equals(poolConfig.getTokenFromSymbol(recieveTokenSymbol).mintKey))!;
1556
+ if (!recieveTokenCustody) {
1557
+ throw "recieveTokenCustody not found";
1558
+ }
1559
+ let publicKey = this.provider.wallet.publicKey;
1560
+
1561
+ const instructions = [];
1562
+ try {
1563
+ let userRecievingTokenAccount = await getAssociatedTokenAddress(
1564
+ recieveTokenCustody.mintKey,
1565
+ publicKey
1566
+ );
1567
+
1568
+ if (!(await checkIfAccountExists(userRecievingTokenAccount, this.provider.connection))) {
1569
+ instructions.push(
1570
+ createAssociatedTokenAccountInstruction(
1571
+ publicKey,
1572
+ userRecievingTokenAccount,
1573
+ publicKey,
1574
+ recieveTokenCustody.mintKey
1575
+ )
1576
+ );
1577
+ }
1578
+ let lpTokenAccount = await getAssociatedTokenAddress(
1579
+ poolConfig.lpTokenMint,
1580
+ publicKey
1581
+ );
1582
+
1583
+ let custodyAccountMetas = [];
1584
+ let custodyOracleAccountMetas = [];
1585
+ for (const custody of poolConfig.custodies) {
1586
+ custodyAccountMetas.push({
1587
+ pubkey: custody.custodyAccount,
1588
+ isSigner: false,
1589
+ isWritable: false,
1590
+ });
1591
+
1592
+ custodyOracleAccountMetas.push({
1593
+ pubkey: custody.oracleAddress,
1594
+ isSigner: false,
1595
+ isWritable: false,
1596
+ });
1597
+ }
1598
+
1599
+ console.log("liquidityAmountIn", liquidityAmountIn.toString());
1600
+
1601
+ let removeLiquidityTx = await this.program.methods
1602
+ .removeLiquidity({
1603
+ lpAmountIn: liquidityAmountIn,
1604
+ minAmountOut: minTokenAmountOut
1605
+ })
1606
+ .accounts({
1607
+ owner: publicKey,
1608
+ receivingAccount: userRecievingTokenAccount, // user token account for custody token account
1609
+ lpTokenAccount,
1610
+ transferAuthority: poolConfig.transferAuthority,
1611
+ perpetuals: poolConfig.perpetuals,
1612
+ pool: poolConfig.poolAddress,
1613
+ custody: recieveTokenCustody.custodyAccount,
1614
+ custodyOracleAccount: recieveTokenCustody.oracleAddress,
1615
+ custodyTokenAccount: recieveTokenCustody.tokenAccount,
1616
+ lpTokenMint: poolConfig.lpTokenMint,
1617
+ tokenProgram: TOKEN_PROGRAM_ID,
1618
+ })
1619
+ .remainingAccounts([...custodyAccountMetas, ...custodyOracleAccountMetas])
1620
+ .instruction();
1621
+ instructions.push(removeLiquidityTx)
1622
+
1623
+ if (closeLpATA) {
1624
+ const closeInx = createCloseAccountInstruction(lpTokenAccount, publicKey, publicKey);
1625
+ instructions.push(closeInx);
1626
+ }
1627
+ } catch (err) {
1628
+ console.log("perpClient removeLiquidity error:: ", err);
1629
+ throw err;
1630
+ }
1631
+
1632
+ return instructions;
1633
+ }
1634
+
1635
+ public async sendTransaction(
1636
+ ixs: TransactionInstruction[],
1637
+ opts: any = {},
1638
+ ): Promise<string> {
1639
+ return await sendTransaction(
1640
+ this.program.provider as AnchorProvider,
1641
+ ixs,
1642
+ opts.alts ?? [],
1643
+ {
1644
+ postSendTxCallback: this.postSendTxCallback,
1645
+ prioritizationFee: this.prioritizationFee,
1646
+ txConfirmationCommitment: this.txConfirmationCommitment,
1647
+ ...opts,
1648
+ },
1649
+ );
1650
+ }
1651
+
1013
1652
  }
1653
+
1654
+