@drift-labs/sdk 0.1.19-master.1 → 0.1.21-master.3

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 (143) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +31 -0
  2. package/lib/accounts/bulkAccountLoader.js +177 -0
  3. package/lib/accounts/bulkUserSubscription.d.ts +7 -0
  4. package/lib/accounts/bulkUserSubscription.js +28 -0
  5. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +49 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +228 -0
  7. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +25 -0
  8. package/lib/accounts/pollingTokenAccountSubscriber.js +79 -0
  9. package/lib/accounts/pollingUserAccountSubscriber.d.ts +32 -0
  10. package/lib/accounts/pollingUserAccountSubscriber.js +136 -0
  11. package/lib/accounts/types.d.ts +38 -3
  12. package/lib/accounts/utils.d.ts +1 -0
  13. package/lib/accounts/utils.js +7 -0
  14. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -3
  15. package/lib/accounts/webSocketAccountSubscriber.js +43 -12
  16. package/lib/accounts/{defaultClearingHouseAccountSubscriber.d.ts → webSocketClearingHouseAccountSubscriber.d.ts} +8 -3
  17. package/lib/accounts/{defaultClearingHouseAccountSubscriber.js → webSocketClearingHouseAccountSubscriber.js} +30 -4
  18. package/lib/accounts/{defaultUserAccountSubscriber.d.ts → webSocketUserAccountSubscriber.d.ts} +6 -3
  19. package/lib/accounts/{defaultUserAccountSubscriber.js → webSocketUserAccountSubscriber.js} +16 -4
  20. package/lib/addresses.d.ts +4 -1
  21. package/lib/addresses.js +28 -1
  22. package/lib/admin.d.ts +10 -4
  23. package/lib/admin.js +54 -17
  24. package/lib/assert/assert.d.ts +0 -1
  25. package/lib/clearingHouse.d.ts +39 -4
  26. package/lib/clearingHouse.js +334 -23
  27. package/lib/clearingHouseUser.d.ts +26 -20
  28. package/lib/clearingHouseUser.js +149 -118
  29. package/lib/config.d.ts +0 -1
  30. package/lib/constants/markets.d.ts +2 -2
  31. package/lib/constants/markets.js +28 -15
  32. package/lib/constants/numericConstants.d.ts +4 -2
  33. package/lib/constants/numericConstants.js +16 -17
  34. package/lib/examples/makeTradeExample.d.ts +0 -1
  35. package/lib/examples/makeTradeExample.js +6 -6
  36. package/lib/factory/clearingHouse.d.ts +25 -0
  37. package/lib/factory/clearingHouse.js +64 -0
  38. package/lib/factory/clearingHouseUser.d.ts +19 -0
  39. package/lib/factory/clearingHouseUser.js +34 -0
  40. package/lib/idl/clearing_house.json +1066 -39
  41. package/lib/index.d.ts +11 -3
  42. package/lib/index.js +12 -2
  43. package/lib/math/amm.d.ts +1 -1
  44. package/lib/math/amm.js +38 -15
  45. package/lib/math/conversion.d.ts +1 -2
  46. package/lib/math/conversion.js +1 -1
  47. package/lib/math/funding.d.ts +0 -1
  48. package/lib/math/funding.js +1 -1
  49. package/lib/math/insuranceFund.d.ts +2 -2
  50. package/lib/math/insuranceFund.js +3 -6
  51. package/lib/math/market.d.ts +2 -2
  52. package/lib/math/market.js +12 -2
  53. package/lib/math/orders.d.ts +3 -0
  54. package/lib/math/orders.js +32 -0
  55. package/lib/math/position.d.ts +6 -3
  56. package/lib/math/position.js +21 -10
  57. package/lib/math/trade.d.ts +0 -1
  58. package/lib/math/trade.js +16 -16
  59. package/lib/math/utils.d.ts +2 -2
  60. package/lib/math/utils.js +3 -3
  61. package/lib/mockUSDCFaucet.d.ts +2 -2
  62. package/lib/orderParams.d.ts +7 -0
  63. package/lib/orderParams.js +108 -0
  64. package/lib/orders.d.ts +6 -0
  65. package/lib/orders.js +136 -0
  66. package/lib/pythClient.d.ts +0 -1
  67. package/lib/pythClient.js +1 -1
  68. package/lib/token/index.d.ts +3 -0
  69. package/lib/token/index.js +38 -0
  70. package/lib/tx/defaultTxSender.d.ts +0 -1
  71. package/lib/tx/types.d.ts +0 -1
  72. package/lib/tx/utils.d.ts +0 -1
  73. package/lib/types.d.ts +147 -3
  74. package/lib/types.js +36 -1
  75. package/lib/util/computeUnits.d.ts +0 -1
  76. package/lib/util/tps.d.ts +0 -1
  77. package/lib/wallet.d.ts +0 -1
  78. package/package.json +11 -3
  79. package/src/accounts/bulkAccountLoader.ts +215 -0
  80. package/src/accounts/bulkUserSubscription.ts +28 -0
  81. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +326 -0
  82. package/src/accounts/pollingTokenAccountSubscriber.ts +99 -0
  83. package/src/accounts/pollingUserAccountSubscriber.ts +194 -0
  84. package/src/accounts/types.ts +48 -1
  85. package/src/accounts/utils.ts +3 -0
  86. package/src/accounts/webSocketAccountSubscriber.ts +67 -17
  87. package/src/accounts/{defaultClearingHouseAccountSubscriber.ts → webSocketClearingHouseAccountSubscriber.ts} +51 -1
  88. package/src/accounts/{defaultUserAccountSubscriber.ts → webSocketUserAccountSubscriber.ts} +33 -3
  89. package/src/addresses.ts +37 -0
  90. package/src/admin.ts +92 -24
  91. package/src/clearingHouse.ts +455 -22
  92. package/src/clearingHouseUser.ts +190 -108
  93. package/src/constants/markets.ts +17 -1
  94. package/src/constants/numericConstants.ts +3 -1
  95. package/src/examples/makeTradeExample.ts +4 -1
  96. package/src/factory/clearingHouse.ts +125 -0
  97. package/src/factory/clearingHouseUser.ts +73 -0
  98. package/src/idl/clearing_house.json +1066 -39
  99. package/src/index.ts +11 -2
  100. package/src/math/amm.ts +47 -14
  101. package/src/math/conversion.ts +1 -1
  102. package/src/math/insuranceFund.ts +1 -1
  103. package/src/math/market.ts +28 -2
  104. package/src/math/orders.ts +44 -0
  105. package/src/math/position.ts +24 -4
  106. package/src/math/utils.ts +1 -1
  107. package/src/mockUSDCFaucet.ts +1 -1
  108. package/src/orderParams.ts +151 -0
  109. package/src/orders.ts +236 -0
  110. package/src/token/index.ts +37 -0
  111. package/src/types.ts +130 -2
  112. package/tsconfig.json +0 -1
  113. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +0 -1
  114. package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +0 -1
  115. package/lib/accounts/types.d.ts.map +0 -1
  116. package/lib/accounts/webSocketAccountSubscriber.d.ts.map +0 -1
  117. package/lib/addresses.d.ts.map +0 -1
  118. package/lib/admin.d.ts.map +0 -1
  119. package/lib/assert/assert.d.ts.map +0 -1
  120. package/lib/clearingHouse.d.ts.map +0 -1
  121. package/lib/clearingHouseUser.d.ts.map +0 -1
  122. package/lib/config.d.ts.map +0 -1
  123. package/lib/constants/markets.d.ts.map +0 -1
  124. package/lib/constants/numericConstants.d.ts.map +0 -1
  125. package/lib/examples/makeTradeExample.d.ts.map +0 -1
  126. package/lib/index.d.ts.map +0 -1
  127. package/lib/math/amm.d.ts.map +0 -1
  128. package/lib/math/conversion.d.ts.map +0 -1
  129. package/lib/math/funding.d.ts.map +0 -1
  130. package/lib/math/insuranceFund.d.ts.map +0 -1
  131. package/lib/math/market.d.ts.map +0 -1
  132. package/lib/math/position.d.ts.map +0 -1
  133. package/lib/math/trade.d.ts.map +0 -1
  134. package/lib/math/utils.d.ts.map +0 -1
  135. package/lib/mockUSDCFaucet.d.ts.map +0 -1
  136. package/lib/pythClient.d.ts.map +0 -1
  137. package/lib/tx/defaultTxSender.d.ts.map +0 -1
  138. package/lib/tx/types.d.ts.map +0 -1
  139. package/lib/tx/utils.d.ts.map +0 -1
  140. package/lib/types.d.ts.map +0 -1
  141. package/lib/util/computeUnits.d.ts.map +0 -1
  142. package/lib/util/tps.d.ts.map +0 -1
  143. package/lib/wallet.d.ts.map +0 -1
@@ -16,6 +16,10 @@ import {
16
16
  TradeHistoryAccount,
17
17
  UserAccount,
18
18
  Market,
19
+ OrderHistoryAccount,
20
+ OrderStateAccount,
21
+ OrderParams,
22
+ Order,
19
23
  ExtendedCurveHistoryAccount,
20
24
  } from './types';
21
25
  import * as anchor from '@project-serum/anchor';
@@ -36,24 +40,30 @@ import { EventEmitter } from 'events';
36
40
  import StrictEventEmitter from 'strict-event-emitter-types';
37
41
  import {
38
42
  getClearingHouseStateAccountPublicKey,
43
+ getOrderStateAccountPublicKey,
39
44
  getUserAccountPublicKey,
40
45
  getUserAccountPublicKeyAndNonce,
46
+ getUserOrdersAccountPublicKey,
47
+ getUserOrdersAccountPublicKeyAndNonce,
41
48
  } from './addresses';
42
49
  import {
43
50
  ClearingHouseAccountSubscriber,
44
51
  ClearingHouseAccountEvents,
45
52
  ClearingHouseAccountTypes,
46
53
  } from './accounts/types';
47
- import { DefaultClearingHouseAccountSubscriber } from './accounts/defaultClearingHouseAccountSubscriber';
48
54
  import { TxSender } from './tx/types';
49
55
  import { DefaultTxSender } from './tx/defaultTxSender';
50
56
  import { wrapInTx } from './tx/utils';
57
+ import {
58
+ getClearingHouse,
59
+ getWebSocketClearingHouseConfig,
60
+ } from './factory/clearingHouse';
51
61
 
52
62
  /**
53
63
  * # ClearingHouse
54
64
  * This class is the main way to interact with Drift Protocol. It allows you to subscribe to the various accounts where the Market's state is stored, as well as: opening positions, liquidating, settling funding, depositing & withdrawing, and more.
55
65
  *
56
- * The default way to construct a ClearingHouse instance is using the {@link from} method. This will create an instance using the static {@link DefaultClearingHouseAccountSubscriber}, which will use a websocket for each state account subscription.
66
+ * The default way to construct a ClearingHouse instance is using the {@link from} method. This will create an instance using the static {@link WebSocketClearingHouseAccountSubscriber}, which will use a websocket for each state account subscription.
57
67
  * Alternatively, if you want to implement your own method of subscribing to the state accounts on the blockchain, you can implement a {@link ClearingHouseAccountSubscriber} and use it in the {@link ClearingHouse.constructor}
58
68
  */
59
69
  export class ClearingHouse {
@@ -64,33 +74,38 @@ export class ClearingHouse {
64
74
  opts?: ConfirmOptions;
65
75
  accountSubscriber: ClearingHouseAccountSubscriber;
66
76
  eventEmitter: StrictEventEmitter<EventEmitter, ClearingHouseAccountEvents>;
67
- isSubscribed = false;
77
+ _isSubscribed = false;
68
78
  txSender: TxSender;
69
79
 
80
+ public get isSubscribed() {
81
+ return this._isSubscribed && this.accountSubscriber.isSubscribed;
82
+ }
83
+
84
+ public set isSubscribed(val: boolean) {
85
+ this._isSubscribed = val;
86
+ }
87
+
88
+ /**
89
+ * @deprecated You should use the getClearingHouse factory method instead
90
+ * @param connection
91
+ * @param wallet
92
+ * @param clearingHouseProgramId
93
+ * @param opts
94
+ * @returns
95
+ */
70
96
  public static from(
71
97
  connection: Connection,
72
98
  wallet: IWallet,
73
99
  clearingHouseProgramId: PublicKey,
74
100
  opts: ConfirmOptions = Provider.defaultOptions()
75
101
  ): ClearingHouse {
76
- const provider = new Provider(connection, wallet, opts);
77
- const program = new Program(
78
- clearingHouseIDL as Idl,
79
- clearingHouseProgramId,
80
- provider
81
- );
82
- const accountSubscriber = new DefaultClearingHouseAccountSubscriber(
83
- program
84
- );
85
- const txSender = new DefaultTxSender(provider);
86
- return new ClearingHouse(
102
+ const config = getWebSocketClearingHouseConfig(
87
103
  connection,
88
104
  wallet,
89
- program,
90
- accountSubscriber,
91
- txSender,
105
+ clearingHouseProgramId,
92
106
  opts
93
107
  );
108
+ return getClearingHouse(config);
94
109
  }
95
110
 
96
111
  public constructor(
@@ -136,6 +151,7 @@ export class ClearingHouse {
136
151
  'fundingRateHistoryAccount',
137
152
  'liquidationHistoryAccount',
138
153
  'tradeHistoryAccount',
154
+ 'orderHistoryAccount',
139
155
  ]);
140
156
  }
141
157
 
@@ -204,6 +220,25 @@ export class ClearingHouse {
204
220
  return this.accountSubscriber.getCurveHistoryAccount();
205
221
  }
206
222
 
223
+ public getOrderHistoryAccount(): OrderHistoryAccount {
224
+ return this.accountSubscriber.getOrderHistoryAccount();
225
+ }
226
+
227
+ orderStatePublicKey?: PublicKey;
228
+ public async getOrderStatePublicKey(): Promise<PublicKey> {
229
+ if (this.orderStatePublicKey) {
230
+ return this.orderStatePublicKey;
231
+ }
232
+ this.orderStatePublicKey = await getOrderStateAccountPublicKey(
233
+ this.program.programId
234
+ );
235
+ return this.orderStatePublicKey;
236
+ }
237
+
238
+ public getOrderStateAccount(): OrderStateAccount {
239
+ return this.accountSubscriber.getOrderStateAccount();
240
+ }
241
+
207
242
  /**
208
243
  * Update the wallet to use for clearing house transactions and linked user account
209
244
  * @param newWallet
@@ -232,9 +267,12 @@ export class ClearingHouse {
232
267
  userPositionsAccount,
233
268
  userAccountPublicKey,
234
269
  initializeUserAccountIx,
270
+ initializeUserOrdersAccountIx,
235
271
  ] = await this.getInitializeUserInstructions();
236
272
 
237
- const tx = new Transaction().add(initializeUserAccountIx);
273
+ const tx = new Transaction()
274
+ .add(initializeUserAccountIx)
275
+ .add(initializeUserOrdersAccountIx);
238
276
  const txSig = await this.txSender.send(
239
277
  tx,
240
278
  [userPositionsAccount],
@@ -244,9 +282,9 @@ export class ClearingHouse {
244
282
  }
245
283
 
246
284
  async getInitializeUserInstructions(): Promise<
247
- [Keypair, PublicKey, TransactionInstruction]
285
+ [Keypair, PublicKey, TransactionInstruction, TransactionInstruction]
248
286
  > {
249
- const [userPublicKey, userAccountNonce] =
287
+ const [userAccountPublicKey, userAccountNonce] =
250
288
  await getUserAccountPublicKeyAndNonce(
251
289
  this.program.programId,
252
290
  this.wallet.publicKey
@@ -280,7 +318,7 @@ export class ClearingHouse {
280
318
  optionalAccounts,
281
319
  {
282
320
  accounts: {
283
- user: userPublicKey,
321
+ user: userAccountPublicKey,
284
322
  authority: this.wallet.publicKey,
285
323
  rent: anchor.web3.SYSVAR_RENT_PUBKEY,
286
324
  systemProgram: anchor.web3.SystemProgram.programId,
@@ -290,7 +328,44 @@ export class ClearingHouse {
290
328
  remainingAccounts: remainingAccounts,
291
329
  }
292
330
  );
293
- return [userPositions, userPublicKey, initializeUserAccountIx];
331
+
332
+ const initializeUserOrdersAccountIx =
333
+ await this.getInitializeUserOrdersInstruction(userAccountPublicKey);
334
+
335
+ return [
336
+ userPositions,
337
+ userAccountPublicKey,
338
+ initializeUserAccountIx,
339
+ initializeUserOrdersAccountIx,
340
+ ];
341
+ }
342
+
343
+ async getInitializeUserOrdersInstruction(
344
+ userAccountPublicKey?: PublicKey
345
+ ): Promise<TransactionInstruction> {
346
+ if (!userAccountPublicKey) {
347
+ userAccountPublicKey = await this.getUserAccountPublicKey();
348
+ }
349
+
350
+ const [userOrdersAccountPublicKey, userOrdersAccountNonce] =
351
+ await getUserOrdersAccountPublicKeyAndNonce(
352
+ this.program.programId,
353
+ userAccountPublicKey
354
+ );
355
+
356
+ return await this.program.instruction.initializeUserOrders(
357
+ userOrdersAccountNonce,
358
+ {
359
+ accounts: {
360
+ user: userAccountPublicKey,
361
+ authority: this.wallet.publicKey,
362
+ rent: anchor.web3.SYSVAR_RENT_PUBKEY,
363
+ systemProgram: anchor.web3.SystemProgram.programId,
364
+ userOrders: userOrdersAccountPublicKey,
365
+ state: await this.getStatePublicKey(),
366
+ },
367
+ }
368
+ );
294
369
  }
295
370
 
296
371
  userAccountPublicKey?: PublicKey;
@@ -322,6 +397,37 @@ export class ClearingHouse {
322
397
  return this.userAccount;
323
398
  }
324
399
 
400
+ userOrdersAccountPublicKey?: PublicKey;
401
+ /**
402
+ * Get the address for the Clearing House User Order's account. NOT the user's wallet address.
403
+ * @returns
404
+ */
405
+ public async getUserOrdersAccountPublicKey(): Promise<PublicKey> {
406
+ if (this.userOrdersAccountPublicKey) {
407
+ return this.userOrdersAccountPublicKey;
408
+ }
409
+
410
+ this.userOrdersAccountPublicKey = await getUserOrdersAccountPublicKey(
411
+ this.program.programId,
412
+ await this.getUserAccountPublicKey()
413
+ );
414
+ return this.userOrdersAccountPublicKey;
415
+ }
416
+
417
+ userOrdersExist?: boolean;
418
+ async userOrdersAccountExists(): Promise<boolean> {
419
+ if (this.userOrdersExist) {
420
+ return this.userOrdersExist;
421
+ }
422
+ const userOrdersAccountRPCResponse =
423
+ await this.connection.getParsedAccountInfo(
424
+ await this.getUserOrdersAccountPublicKey()
425
+ );
426
+
427
+ this.userOrdersExist = userOrdersAccountRPCResponse.value !== null;
428
+ return this.userOrdersExist;
429
+ }
430
+
325
431
  public async depositCollateral(
326
432
  amount: BN,
327
433
  collateralAccountPublicKey: PublicKey,
@@ -379,6 +485,7 @@ export class ClearingHouse {
379
485
  userPositionsAccount,
380
486
  userAccountPublicKey,
381
487
  initializeUserAccountIx,
488
+ initializeUserOrdersAccountIx,
382
489
  ] = await this.getInitializeUserInstructions();
383
490
 
384
491
  const depositCollateralIx = await this.getDepositCollateralInstruction(
@@ -389,6 +496,7 @@ export class ClearingHouse {
389
496
 
390
497
  const tx = new Transaction()
391
498
  .add(initializeUserAccountIx)
499
+ .add(initializeUserOrdersAccountIx)
392
500
  .add(depositCollateralIx);
393
501
 
394
502
  const txSig = await this.program.provider.send(tx, [userPositionsAccount]);
@@ -410,6 +518,7 @@ export class ClearingHouse {
410
518
  userPositionsAccount,
411
519
  userAccountPublicKey,
412
520
  initializeUserAccountIx,
521
+ initializeUserOrdersAccountIx,
413
522
  ] = await this.getInitializeUserInstructions();
414
523
 
415
524
  const depositCollateralIx = await this.getDepositCollateralInstruction(
@@ -422,6 +531,7 @@ export class ClearingHouse {
422
531
  .add(createAssociatedAccountIx)
423
532
  .add(mintToIx)
424
533
  .add(initializeUserAccountIx)
534
+ .add(initializeUserOrdersAccountIx)
425
535
  .add(depositCollateralIx);
426
536
 
427
537
  const txSig = await this.program.provider.send(tx, [userPositionsAccount]);
@@ -572,6 +682,329 @@ export class ClearingHouse {
572
682
  );
573
683
  }
574
684
 
685
+ public async initializeUserOrdersThenPlaceOrder(
686
+ orderParams: OrderParams,
687
+ discountToken?: PublicKey,
688
+ referrer?: PublicKey
689
+ ): Promise<TransactionSignature> {
690
+ const instructions: anchor.web3.TransactionInstruction[] = [];
691
+ const userOrdersAccountExists = await this.userOrdersAccountExists();
692
+ if (!userOrdersAccountExists) {
693
+ instructions.push(await this.getInitializeUserOrdersInstruction());
694
+ }
695
+ instructions.push(
696
+ await this.getPlaceOrderIx(orderParams, discountToken, referrer)
697
+ );
698
+ const tx = new Transaction();
699
+ for (const instruction of instructions) {
700
+ tx.add(instruction);
701
+ }
702
+
703
+ return await this.txSender.send(tx, [], this.opts);
704
+ }
705
+
706
+ public async placeOrder(
707
+ orderParams: OrderParams,
708
+ discountToken?: PublicKey,
709
+ referrer?: PublicKey
710
+ ): Promise<TransactionSignature> {
711
+ return await this.txSender.send(
712
+ wrapInTx(
713
+ await this.getPlaceOrderIx(orderParams, discountToken, referrer)
714
+ ),
715
+ [],
716
+ this.opts
717
+ );
718
+ }
719
+
720
+ public async getPlaceOrderIx(
721
+ orderParams: OrderParams,
722
+ discountToken?: PublicKey,
723
+ referrer?: PublicKey
724
+ ): Promise<TransactionInstruction> {
725
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
726
+ const userAccount = await this.getUserAccount();
727
+
728
+ const priceOracle =
729
+ this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
730
+ .oracle;
731
+
732
+ const remainingAccounts = [];
733
+ if (orderParams.optionalAccounts.discountToken) {
734
+ if (!discountToken) {
735
+ throw Error(
736
+ 'Optional accounts specified discount token but no discount token present'
737
+ );
738
+ }
739
+
740
+ remainingAccounts.push({
741
+ pubkey: discountToken,
742
+ isWritable: false,
743
+ isSigner: false,
744
+ });
745
+ }
746
+
747
+ if (orderParams.optionalAccounts.referrer) {
748
+ if (!referrer) {
749
+ throw Error(
750
+ 'Optional accounts specified referrer but no referrer present'
751
+ );
752
+ }
753
+
754
+ remainingAccounts.push({
755
+ pubkey: referrer,
756
+ isWritable: false,
757
+ isSigner: false,
758
+ });
759
+ }
760
+
761
+ const state = this.getStateAccount();
762
+ const orderState = this.getOrderStateAccount();
763
+ return await this.program.instruction.placeOrder(orderParams, {
764
+ accounts: {
765
+ state: await this.getStatePublicKey(),
766
+ user: userAccountPublicKey,
767
+ authority: this.wallet.publicKey,
768
+ markets: state.markets,
769
+ userOrders: await this.getUserOrdersAccountPublicKey(),
770
+ userPositions: userAccount.positions,
771
+ fundingPaymentHistory: state.fundingPaymentHistory,
772
+ fundingRateHistory: state.fundingRateHistory,
773
+ orderState: await this.getOrderStatePublicKey(),
774
+ orderHistory: orderState.orderHistory,
775
+ oracle: priceOracle,
776
+ },
777
+ remainingAccounts,
778
+ });
779
+ }
780
+
781
+ public async cancelOrder(orderId: BN): Promise<TransactionSignature> {
782
+ return await this.txSender.send(
783
+ wrapInTx(await this.getCancelOrderIx(orderId)),
784
+ [],
785
+ this.opts
786
+ );
787
+ }
788
+
789
+ public async getCancelOrderIx(orderId: BN): Promise<TransactionInstruction> {
790
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
791
+ const userAccount = await this.getUserAccount();
792
+
793
+ const state = this.getStateAccount();
794
+ const orderState = this.getOrderStateAccount();
795
+ return await this.program.instruction.cancelOrder(orderId, {
796
+ accounts: {
797
+ state: await this.getStatePublicKey(),
798
+ user: userAccountPublicKey,
799
+ authority: this.wallet.publicKey,
800
+ markets: state.markets,
801
+ userOrders: await this.getUserOrdersAccountPublicKey(),
802
+ userPositions: userAccount.positions,
803
+ fundingPaymentHistory: state.fundingPaymentHistory,
804
+ fundingRateHistory: state.fundingRateHistory,
805
+ orderState: await this.getOrderStatePublicKey(),
806
+ orderHistory: orderState.orderHistory,
807
+ },
808
+ });
809
+ }
810
+
811
+ public async cancelOrderByUserId(
812
+ userOrderId: number
813
+ ): Promise<TransactionSignature> {
814
+ return await this.txSender.send(
815
+ wrapInTx(await this.getCancelOrderByUserIdIx(userOrderId)),
816
+ [],
817
+ this.opts
818
+ );
819
+ }
820
+
821
+ public async getCancelOrderByUserIdIx(
822
+ userOrderId: number
823
+ ): Promise<TransactionInstruction> {
824
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
825
+ const userAccount = await this.getUserAccount();
826
+
827
+ const state = this.getStateAccount();
828
+ const orderState = this.getOrderStateAccount();
829
+ return await this.program.instruction.cancelOrderByUserId(userOrderId, {
830
+ accounts: {
831
+ state: await this.getStatePublicKey(),
832
+ user: userAccountPublicKey,
833
+ authority: this.wallet.publicKey,
834
+ markets: state.markets,
835
+ userOrders: await this.getUserOrdersAccountPublicKey(),
836
+ userPositions: userAccount.positions,
837
+ fundingPaymentHistory: state.fundingPaymentHistory,
838
+ fundingRateHistory: state.fundingRateHistory,
839
+ orderState: await this.getOrderStatePublicKey(),
840
+ orderHistory: orderState.orderHistory,
841
+ },
842
+ });
843
+ }
844
+
845
+ public async fillOrder(
846
+ userAccountPublicKey: PublicKey,
847
+ userOrdersAccountPublicKey: PublicKey,
848
+ order: Order
849
+ ): Promise<TransactionSignature> {
850
+ return await this.txSender.send(
851
+ wrapInTx(
852
+ await this.getFillOrderIx(
853
+ userAccountPublicKey,
854
+ userOrdersAccountPublicKey,
855
+ order
856
+ )
857
+ ),
858
+ [],
859
+ this.opts
860
+ );
861
+ }
862
+
863
+ public async getFillOrderIx(
864
+ userAccountPublicKey: PublicKey,
865
+ userOrdersAccountPublicKey: PublicKey,
866
+ order: Order
867
+ ): Promise<TransactionInstruction> {
868
+ const fillerPublicKey = await this.getUserAccountPublicKey();
869
+ const userAccount: any = await this.program.account.user.fetch(
870
+ userAccountPublicKey
871
+ );
872
+
873
+ const marketIndex = order.marketIndex;
874
+ const oracle = this.getMarket(marketIndex).amm.oracle;
875
+
876
+ const state = this.getStateAccount();
877
+ const orderState = this.getOrderStateAccount();
878
+
879
+ const remainingAccounts = [];
880
+ if (!order.referrer.equals(PublicKey.default)) {
881
+ remainingAccounts.push({
882
+ pubkey: order.referrer,
883
+ isWritable: true,
884
+ isSigner: false,
885
+ });
886
+ }
887
+
888
+ const orderId = order.orderId;
889
+ return await this.program.instruction.fillOrder(orderId, {
890
+ accounts: {
891
+ state: await this.getStatePublicKey(),
892
+ filler: fillerPublicKey,
893
+ user: userAccountPublicKey,
894
+ authority: this.wallet.publicKey,
895
+ markets: state.markets,
896
+ userPositions: userAccount.positions,
897
+ userOrders: userOrdersAccountPublicKey,
898
+ tradeHistory: state.tradeHistory,
899
+ fundingPaymentHistory: state.fundingPaymentHistory,
900
+ fundingRateHistory: state.fundingRateHistory,
901
+ orderState: await this.getOrderStatePublicKey(),
902
+ orderHistory: orderState.orderHistory,
903
+ extendedCurveHistory: state.extendedCurveHistory,
904
+ oracle: oracle,
905
+ },
906
+ remainingAccounts,
907
+ });
908
+ }
909
+
910
+ public async initializeUserOrdersThenPlaceAndFillOrder(
911
+ orderParams: OrderParams,
912
+ discountToken?: PublicKey,
913
+ referrer?: PublicKey
914
+ ): Promise<TransactionSignature> {
915
+ const instructions: anchor.web3.TransactionInstruction[] = [];
916
+ const userOrdersAccountExists = await this.userOrdersAccountExists();
917
+ if (!userOrdersAccountExists) {
918
+ instructions.push(await this.getInitializeUserOrdersInstruction());
919
+ }
920
+ instructions.push(
921
+ await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
922
+ );
923
+ const tx = new Transaction();
924
+ for (const instruction of instructions) {
925
+ tx.add(instruction);
926
+ }
927
+
928
+ return await this.txSender.send(tx, [], this.opts);
929
+ }
930
+
931
+ public async placeAndFillOrder(
932
+ orderParams: OrderParams,
933
+ discountToken?: PublicKey,
934
+ referrer?: PublicKey
935
+ ): Promise<TransactionSignature> {
936
+ return await this.txSender.send(
937
+ wrapInTx(
938
+ await this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)
939
+ ),
940
+ [],
941
+ this.opts
942
+ );
943
+ }
944
+
945
+ public async getPlaceAndFillOrderIx(
946
+ orderParams: OrderParams,
947
+ discountToken?: PublicKey,
948
+ referrer?: PublicKey
949
+ ): Promise<TransactionInstruction> {
950
+ const userAccountPublicKey = await this.getUserAccountPublicKey();
951
+ const userAccount = await this.getUserAccount();
952
+
953
+ const priceOracle =
954
+ this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
955
+ .oracle;
956
+
957
+ const remainingAccounts = [];
958
+ if (orderParams.optionalAccounts.discountToken) {
959
+ if (!discountToken) {
960
+ throw Error(
961
+ 'Optional accounts specified discount token but no discount token present'
962
+ );
963
+ }
964
+
965
+ remainingAccounts.push({
966
+ pubkey: discountToken,
967
+ isWritable: false,
968
+ isSigner: false,
969
+ });
970
+ }
971
+
972
+ if (orderParams.optionalAccounts.referrer) {
973
+ if (!referrer) {
974
+ throw Error(
975
+ 'Optional accounts specified referrer but no referrer present'
976
+ );
977
+ }
978
+
979
+ remainingAccounts.push({
980
+ pubkey: referrer,
981
+ isWritable: true,
982
+ isSigner: false,
983
+ });
984
+ }
985
+
986
+ const state = this.getStateAccount();
987
+ const orderState = this.getOrderStateAccount();
988
+ return await this.program.instruction.placeAndFillOrder(orderParams, {
989
+ accounts: {
990
+ state: await this.getStatePublicKey(),
991
+ user: userAccountPublicKey,
992
+ authority: this.wallet.publicKey,
993
+ markets: state.markets,
994
+ userOrders: await this.getUserOrdersAccountPublicKey(),
995
+ userPositions: userAccount.positions,
996
+ tradeHistory: state.tradeHistory,
997
+ fundingPaymentHistory: state.fundingPaymentHistory,
998
+ fundingRateHistory: state.fundingRateHistory,
999
+ orderState: await this.getOrderStatePublicKey(),
1000
+ orderHistory: orderState.orderHistory,
1001
+ extendedCurveHistory: state.extendedCurveHistory,
1002
+ oracle: priceOracle,
1003
+ },
1004
+ remainingAccounts,
1005
+ });
1006
+ }
1007
+
575
1008
  /**
576
1009
  * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
577
1010
  * @param marketIndex