@drift-labs/sdk 0.1.17 → 0.1.18-orders.0

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 (103) hide show
  1. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts +5 -2
  2. package/lib/accounts/defaultClearingHouseAccountSubscriber.js +25 -0
  3. package/lib/accounts/defaultHistoryAccountSubscriber.d.ts +28 -0
  4. package/lib/accounts/defaultHistoryAccountSubscriber.js +110 -0
  5. package/lib/accounts/defaultUserAccountSubscriber.d.ts +3 -2
  6. package/lib/accounts/defaultUserAccountSubscriber.js +11 -0
  7. package/lib/accounts/types.d.ts +29 -3
  8. package/lib/accounts/webSocketAccountSubscriber.d.ts +0 -1
  9. package/lib/addresses.d.ts +4 -1
  10. package/lib/addresses.js +28 -1
  11. package/lib/admin.d.ts +10 -4
  12. package/lib/admin.js +48 -3
  13. package/lib/assert/assert.d.ts +0 -1
  14. package/lib/clearingHouse.d.ts +21 -2
  15. package/lib/clearingHouse.js +238 -7
  16. package/lib/clearingHouseUser.d.ts +10 -17
  17. package/lib/clearingHouseUser.js +98 -84
  18. package/lib/config.d.ts +0 -1
  19. package/lib/config.js +1 -1
  20. package/lib/constants/markets.d.ts +0 -1
  21. package/lib/constants/numericConstants.d.ts +0 -1
  22. package/lib/examples/makeTradeExample.d.ts +0 -1
  23. package/lib/idl/clearing_house.json +956 -59
  24. package/lib/index.d.ts +3 -1
  25. package/lib/index.js +3 -0
  26. package/lib/math/amm.d.ts +1 -1
  27. package/lib/math/amm.js +31 -8
  28. package/lib/math/conversion.d.ts +0 -1
  29. package/lib/math/funding.d.ts +0 -1
  30. package/lib/math/insuranceFund.d.ts +0 -1
  31. package/lib/math/market.d.ts +2 -2
  32. package/lib/math/market.js +11 -1
  33. package/lib/math/orders.d.ts +3 -0
  34. package/lib/math/orders.js +30 -0
  35. package/lib/math/position.d.ts +4 -2
  36. package/lib/math/position.js +18 -4
  37. package/lib/math/trade.d.ts +0 -1
  38. package/lib/math/utils.d.ts +0 -1
  39. package/lib/mockUSDCFaucet.d.ts +0 -1
  40. package/lib/orderParams.d.ts +7 -0
  41. package/lib/orderParams.js +88 -0
  42. package/lib/orders.d.ts +5 -0
  43. package/lib/orders.js +136 -0
  44. package/lib/pythClient.d.ts +0 -1
  45. package/lib/tx/defaultTxSender.d.ts +0 -1
  46. package/lib/tx/types.d.ts +0 -1
  47. package/lib/tx/utils.d.ts +0 -1
  48. package/lib/types.d.ts +137 -2
  49. package/lib/types.js +36 -1
  50. package/lib/util/computeUnits.d.ts +0 -1
  51. package/lib/util/tps.d.ts +0 -1
  52. package/lib/wallet.d.ts +0 -1
  53. package/package.json +1 -1
  54. package/src/accounts/defaultClearingHouseAccountSubscriber.ts +47 -0
  55. package/src/accounts/defaultHistoryAccountSubscriber.ts +176 -0
  56. package/src/accounts/defaultUserAccountSubscriber.ts +29 -2
  57. package/src/accounts/types.ts +38 -1
  58. package/src/addresses.ts +35 -0
  59. package/src/admin.ts +84 -6
  60. package/src/clearingHouse.ts +338 -5
  61. package/src/clearingHouseUser.ts +154 -102
  62. package/src/config.ts +1 -1
  63. package/src/idl/clearing_house.json +956 -59
  64. package/src/index.ts +3 -0
  65. package/src/math/amm.ts +47 -14
  66. package/src/math/market.ts +28 -2
  67. package/src/math/orders.ts +39 -0
  68. package/src/math/position.ts +23 -3
  69. package/src/orderParams.ts +128 -0
  70. package/src/orders.ts +230 -0
  71. package/src/types.ts +121 -1
  72. package/tsconfig.json +0 -1
  73. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +0 -1
  74. package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +0 -1
  75. package/lib/accounts/types.d.ts.map +0 -1
  76. package/lib/accounts/webSocketAccountSubscriber.d.ts.map +0 -1
  77. package/lib/addresses.d.ts.map +0 -1
  78. package/lib/admin.d.ts.map +0 -1
  79. package/lib/assert/assert.d.ts.map +0 -1
  80. package/lib/clearingHouse.d.ts.map +0 -1
  81. package/lib/clearingHouseUser.d.ts.map +0 -1
  82. package/lib/config.d.ts.map +0 -1
  83. package/lib/constants/markets.d.ts.map +0 -1
  84. package/lib/constants/numericConstants.d.ts.map +0 -1
  85. package/lib/examples/makeTradeExample.d.ts.map +0 -1
  86. package/lib/index.d.ts.map +0 -1
  87. package/lib/math/amm.d.ts.map +0 -1
  88. package/lib/math/conversion.d.ts.map +0 -1
  89. package/lib/math/funding.d.ts.map +0 -1
  90. package/lib/math/insuranceFund.d.ts.map +0 -1
  91. package/lib/math/market.d.ts.map +0 -1
  92. package/lib/math/position.d.ts.map +0 -1
  93. package/lib/math/trade.d.ts.map +0 -1
  94. package/lib/math/utils.d.ts.map +0 -1
  95. package/lib/mockUSDCFaucet.d.ts.map +0 -1
  96. package/lib/pythClient.d.ts.map +0 -1
  97. package/lib/tx/defaultTxSender.d.ts.map +0 -1
  98. package/lib/tx/types.d.ts.map +0 -1
  99. package/lib/tx/utils.d.ts.map +0 -1
  100. package/lib/types.d.ts.map +0 -1
  101. package/lib/util/computeUnits.d.ts.map +0 -1
  102. package/lib/util/tps.d.ts.map +0 -1
  103. package/lib/wallet.d.ts.map +0 -1
@@ -90,6 +90,7 @@ class ClearingHouse {
90
90
  'fundingRateHistoryAccount',
91
91
  'liquidationHistoryAccount',
92
92
  'tradeHistoryAccount',
93
+ 'orderHistoryAccount',
93
94
  ]);
94
95
  });
95
96
  }
@@ -149,6 +150,21 @@ class ClearingHouse {
149
150
  getCurveHistoryAccount() {
150
151
  return this.accountSubscriber.getCurveHistoryAccount();
151
152
  }
153
+ getOrderHistoryAccount() {
154
+ return this.accountSubscriber.getOrderHistoryAccount();
155
+ }
156
+ getOrderStatePublicKey() {
157
+ return __awaiter(this, void 0, void 0, function* () {
158
+ if (this.orderStatePublicKey) {
159
+ return this.orderStatePublicKey;
160
+ }
161
+ this.orderStatePublicKey = yield addresses_1.getOrderStateAccountPublicKey(this.program.programId);
162
+ return this.orderStatePublicKey;
163
+ });
164
+ }
165
+ getOrderStateAccount() {
166
+ return this.accountSubscriber.getOrderStateAccount();
167
+ }
152
168
  /**
153
169
  * Update the wallet to use for clearing house transactions and linked user account
154
170
  * @param newWallet
@@ -166,15 +182,17 @@ class ClearingHouse {
166
182
  }
167
183
  initializeUserAccount() {
168
184
  return __awaiter(this, void 0, void 0, function* () {
169
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx,] = yield this.getInitializeUserInstructions();
170
- const tx = new web3_js_1.Transaction().add(initializeUserAccountIx);
185
+ const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
186
+ const tx = new web3_js_1.Transaction()
187
+ .add(initializeUserAccountIx)
188
+ .add(initializeUserOrdersAccountIx);
171
189
  const txSig = yield this.txSender.send(tx, [userPositionsAccount], this.opts);
172
190
  return [txSig, userAccountPublicKey];
173
191
  });
174
192
  }
175
193
  getInitializeUserInstructions() {
176
194
  return __awaiter(this, void 0, void 0, function* () {
177
- const [userPublicKey, userAccountNonce] = yield addresses_1.getUserAccountPublicKeyAndNonce(this.program.programId, this.wallet.publicKey);
195
+ const [userAccountPublicKey, userAccountNonce] = yield addresses_1.getUserAccountPublicKeyAndNonce(this.program.programId, this.wallet.publicKey);
178
196
  const remainingAccounts = [];
179
197
  const optionalAccounts = {
180
198
  whitelistToken: false,
@@ -192,7 +210,7 @@ class ClearingHouse {
192
210
  const userPositions = new web3_js_1.Keypair();
193
211
  const initializeUserAccountIx = yield this.program.instruction.initializeUser(userAccountNonce, optionalAccounts, {
194
212
  accounts: {
195
- user: userPublicKey,
213
+ user: userAccountPublicKey,
196
214
  authority: this.wallet.publicKey,
197
215
  rent: anchor.web3.SYSVAR_RENT_PUBKEY,
198
216
  systemProgram: anchor.web3.SystemProgram.programId,
@@ -201,7 +219,31 @@ class ClearingHouse {
201
219
  },
202
220
  remainingAccounts: remainingAccounts,
203
221
  });
204
- return [userPositions, userPublicKey, initializeUserAccountIx];
222
+ const initializeUserOrdersAccountIx = yield this.getInitializeUserOrdersInstruction(userAccountPublicKey);
223
+ return [
224
+ userPositions,
225
+ userAccountPublicKey,
226
+ initializeUserAccountIx,
227
+ initializeUserOrdersAccountIx,
228
+ ];
229
+ });
230
+ }
231
+ getInitializeUserOrdersInstruction(userAccountPublicKey) {
232
+ return __awaiter(this, void 0, void 0, function* () {
233
+ const [userOrdersAccountPublicKey, userOrdersAccountNonce] = yield addresses_1.getUserOrdersAccountPublicKeyAndNonce(this.program.programId, this.wallet.publicKey);
234
+ if (!userAccountPublicKey) {
235
+ userAccountPublicKey = yield this.getUserAccountPublicKey();
236
+ }
237
+ return yield this.program.instruction.initializeUserOrders(userOrdersAccountNonce, {
238
+ accounts: {
239
+ user: userAccountPublicKey,
240
+ authority: this.wallet.publicKey,
241
+ rent: anchor.web3.SYSVAR_RENT_PUBKEY,
242
+ systemProgram: anchor.web3.SystemProgram.programId,
243
+ userOrders: userOrdersAccountPublicKey,
244
+ state: yield this.getStatePublicKey(),
245
+ },
246
+ });
205
247
  });
206
248
  }
207
249
  /**
@@ -226,6 +268,19 @@ class ClearingHouse {
226
268
  return this.userAccount;
227
269
  });
228
270
  }
271
+ /**
272
+ * Get the address for the Clearing House User Order's account. NOT the user's wallet address.
273
+ * @returns
274
+ */
275
+ getUserOrdersAccountPublicKey() {
276
+ return __awaiter(this, void 0, void 0, function* () {
277
+ if (this.userOrdersAccountPublicKey) {
278
+ return this.userOrdersAccountPublicKey;
279
+ }
280
+ this.userOrdersAccountPublicKey = yield addresses_1.getUserOrdersAccountPublicKey(this.program.programId, this.wallet.publicKey);
281
+ return this.userOrdersAccountPublicKey;
282
+ });
283
+ }
229
284
  depositCollateral(amount, collateralAccountPublicKey, userPositionsAccountPublicKey) {
230
285
  return __awaiter(this, void 0, void 0, function* () {
231
286
  const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, collateralAccountPublicKey, userPositionsAccountPublicKey);
@@ -264,10 +319,11 @@ class ClearingHouse {
264
319
  */
265
320
  initializeUserAccountAndDepositCollateral(amount, collateralAccountPublicKey) {
266
321
  return __awaiter(this, void 0, void 0, function* () {
267
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx,] = yield this.getInitializeUserInstructions();
322
+ const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
268
323
  const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, collateralAccountPublicKey, userPositionsAccount.publicKey);
269
324
  const tx = new web3_js_1.Transaction()
270
325
  .add(initializeUserAccountIx)
326
+ .add(initializeUserOrdersAccountIx)
271
327
  .add(depositCollateralIx);
272
328
  const txSig = yield this.program.provider.send(tx, [userPositionsAccount]);
273
329
  return [txSig, userAccountPublicKey];
@@ -276,12 +332,13 @@ class ClearingHouse {
276
332
  initializeUserAccountForDevnet(mockUSDCFaucet, amount) {
277
333
  return __awaiter(this, void 0, void 0, function* () {
278
334
  const [associateTokenPublicKey, createAssociatedAccountIx, mintToIx] = yield mockUSDCFaucet.createAssociatedTokenAccountAndMintToInstructions(this.wallet.publicKey, amount);
279
- const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx,] = yield this.getInitializeUserInstructions();
335
+ const [userPositionsAccount, userAccountPublicKey, initializeUserAccountIx, initializeUserOrdersAccountIx,] = yield this.getInitializeUserInstructions();
280
336
  const depositCollateralIx = yield this.getDepositCollateralInstruction(amount, associateTokenPublicKey, userPositionsAccount.publicKey);
281
337
  const tx = new web3_js_1.Transaction()
282
338
  .add(createAssociatedAccountIx)
283
339
  .add(mintToIx)
284
340
  .add(initializeUserAccountIx)
341
+ .add(initializeUserOrdersAccountIx)
285
342
  .add(depositCollateralIx);
286
343
  const txSig = yield this.program.provider.send(tx, [userPositionsAccount]);
287
344
  return [txSig, userAccountPublicKey];
@@ -381,6 +438,180 @@ class ClearingHouse {
381
438
  });
382
439
  });
383
440
  }
441
+ placeOrder(orderParams, discountToken, referrer) {
442
+ return __awaiter(this, void 0, void 0, function* () {
443
+ return yield this.txSender.send(utils_1.wrapInTx(yield this.getPlaceOrderIx(orderParams, discountToken, referrer)), [], this.opts);
444
+ });
445
+ }
446
+ getPlaceOrderIx(orderParams, discountToken, referrer) {
447
+ return __awaiter(this, void 0, void 0, function* () {
448
+ const userAccountPublicKey = yield this.getUserAccountPublicKey();
449
+ const userAccount = yield this.getUserAccount();
450
+ const priceOracle = this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
451
+ .oracle;
452
+ const remainingAccounts = [];
453
+ if (orderParams.optionalAccounts.discountToken) {
454
+ if (!discountToken) {
455
+ throw Error('Optional accounts specified discount token but no discount token present');
456
+ }
457
+ remainingAccounts.push({
458
+ pubkey: discountToken,
459
+ isWritable: false,
460
+ isSigner: false,
461
+ });
462
+ }
463
+ if (orderParams.optionalAccounts.referrer) {
464
+ if (!referrer) {
465
+ throw Error('Optional accounts specified referrer but no referrer present');
466
+ }
467
+ remainingAccounts.push({
468
+ pubkey: referrer,
469
+ isWritable: false,
470
+ isSigner: false,
471
+ });
472
+ }
473
+ const state = this.getStateAccount();
474
+ const orderState = this.getOrderStateAccount();
475
+ return yield this.program.instruction.placeOrder(orderParams, {
476
+ accounts: {
477
+ state: yield this.getStatePublicKey(),
478
+ user: userAccountPublicKey,
479
+ authority: this.wallet.publicKey,
480
+ markets: state.markets,
481
+ userOrders: yield this.getUserOrdersAccountPublicKey(),
482
+ userPositions: userAccount.positions,
483
+ fundingPaymentHistory: state.fundingPaymentHistory,
484
+ fundingRateHistory: state.fundingRateHistory,
485
+ orderState: yield this.getOrderStatePublicKey(),
486
+ orderHistory: orderState.orderHistory,
487
+ oracle: priceOracle,
488
+ },
489
+ remainingAccounts,
490
+ });
491
+ });
492
+ }
493
+ cancelOrder(orderId) {
494
+ return __awaiter(this, void 0, void 0, function* () {
495
+ return yield this.txSender.send(utils_1.wrapInTx(yield this.getCancelOrderIx(orderId)), [], this.opts);
496
+ });
497
+ }
498
+ getCancelOrderIx(orderId) {
499
+ return __awaiter(this, void 0, void 0, function* () {
500
+ const userAccountPublicKey = yield this.getUserAccountPublicKey();
501
+ const userAccount = yield this.getUserAccount();
502
+ const state = this.getStateAccount();
503
+ const orderState = this.getOrderStateAccount();
504
+ return yield this.program.instruction.cancelOrder(orderId, {
505
+ accounts: {
506
+ state: yield this.getStatePublicKey(),
507
+ user: userAccountPublicKey,
508
+ authority: this.wallet.publicKey,
509
+ markets: state.markets,
510
+ userOrders: yield this.getUserOrdersAccountPublicKey(),
511
+ userPositions: userAccount.positions,
512
+ fundingPaymentHistory: state.fundingPaymentHistory,
513
+ fundingRateHistory: state.fundingRateHistory,
514
+ orderState: yield this.getOrderStatePublicKey(),
515
+ orderHistory: orderState.orderHistory,
516
+ },
517
+ });
518
+ });
519
+ }
520
+ fillOrder(userAccountPublicKey, userOrdersAccountPublicKey, order) {
521
+ return __awaiter(this, void 0, void 0, function* () {
522
+ return yield this.txSender.send(utils_1.wrapInTx(yield this.getFillOrderIx(userAccountPublicKey, userOrdersAccountPublicKey, order)), [], this.opts);
523
+ });
524
+ }
525
+ getFillOrderIx(userAccountPublicKey, userOrdersAccountPublicKey, order) {
526
+ return __awaiter(this, void 0, void 0, function* () {
527
+ const fillerPublicKey = yield this.getUserAccountPublicKey();
528
+ const userAccount = yield this.program.account.user.fetch(userAccountPublicKey);
529
+ const marketIndex = order.marketIndex;
530
+ const oracle = this.getMarket(marketIndex).amm.oracle;
531
+ const state = this.getStateAccount();
532
+ const orderState = this.getOrderStateAccount();
533
+ const remainingAccounts = [];
534
+ if (!order.referrer.equals(web3_js_1.PublicKey.default)) {
535
+ remainingAccounts.push({
536
+ pubkey: order.referrer,
537
+ isWritable: true,
538
+ isSigner: false,
539
+ });
540
+ }
541
+ const orderId = order.orderId;
542
+ return yield this.program.instruction.fillOrder(orderId, {
543
+ accounts: {
544
+ state: yield this.getStatePublicKey(),
545
+ filler: fillerPublicKey,
546
+ user: userAccountPublicKey,
547
+ authority: this.wallet.publicKey,
548
+ markets: state.markets,
549
+ userPositions: userAccount.positions,
550
+ userOrders: userOrdersAccountPublicKey,
551
+ tradeHistory: state.tradeHistory,
552
+ fundingPaymentHistory: state.fundingPaymentHistory,
553
+ fundingRateHistory: state.fundingRateHistory,
554
+ orderState: yield this.getOrderStatePublicKey(),
555
+ orderHistory: orderState.orderHistory,
556
+ oracle: oracle,
557
+ },
558
+ remainingAccounts,
559
+ });
560
+ });
561
+ }
562
+ placeAndFillOrder(orderParams, discountToken, referrer) {
563
+ return __awaiter(this, void 0, void 0, function* () {
564
+ return yield this.txSender.send(utils_1.wrapInTx(yield this.getPlaceAndFillOrderIx(orderParams, discountToken, referrer)), [], this.opts);
565
+ });
566
+ }
567
+ getPlaceAndFillOrderIx(orderParams, discountToken, referrer) {
568
+ return __awaiter(this, void 0, void 0, function* () {
569
+ const userAccountPublicKey = yield this.getUserAccountPublicKey();
570
+ const userAccount = yield this.getUserAccount();
571
+ const priceOracle = this.getMarketsAccount().markets[orderParams.marketIndex.toNumber()].amm
572
+ .oracle;
573
+ const remainingAccounts = [];
574
+ if (orderParams.optionalAccounts.discountToken) {
575
+ if (!discountToken) {
576
+ throw Error('Optional accounts specified discount token but no discount token present');
577
+ }
578
+ remainingAccounts.push({
579
+ pubkey: discountToken,
580
+ isWritable: false,
581
+ isSigner: false,
582
+ });
583
+ }
584
+ if (orderParams.optionalAccounts.referrer) {
585
+ if (!referrer) {
586
+ throw Error('Optional accounts specified referrer but no referrer present');
587
+ }
588
+ remainingAccounts.push({
589
+ pubkey: referrer,
590
+ isWritable: true,
591
+ isSigner: false,
592
+ });
593
+ }
594
+ const state = this.getStateAccount();
595
+ const orderState = this.getOrderStateAccount();
596
+ return yield this.program.instruction.placeAndFillOrder(orderParams, {
597
+ accounts: {
598
+ state: yield this.getStatePublicKey(),
599
+ user: userAccountPublicKey,
600
+ authority: this.wallet.publicKey,
601
+ markets: state.markets,
602
+ userOrders: yield this.getUserOrdersAccountPublicKey(),
603
+ userPositions: userAccount.positions,
604
+ tradeHistory: state.tradeHistory,
605
+ fundingPaymentHistory: state.fundingPaymentHistory,
606
+ fundingRateHistory: state.fundingRateHistory,
607
+ orderState: yield this.getOrderStatePublicKey(),
608
+ orderHistory: orderState.orderHistory,
609
+ oracle: priceOracle,
610
+ },
611
+ remainingAccounts,
612
+ });
613
+ });
614
+ }
384
615
  /**
385
616
  * Close an entire position. If you want to reduce a position, use the {@link openPosition} method in the opposite direction of the current position.
386
617
  * @param marketIndex
@@ -4,7 +4,7 @@ import BN from 'bn.js';
4
4
  import { EventEmitter } from 'events';
5
5
  import StrictEventEmitter from 'strict-event-emitter-types';
6
6
  import { ClearingHouse } from './clearingHouse';
7
- import { UserAccount, UserPosition, UserPositionsAccount } from './types';
7
+ import { Order, UserAccount, UserOrdersAccount, UserPosition, UserPositionsAccount } from './types';
8
8
  import { UserAccountSubscriber, UserAccountEvents } from './accounts/types';
9
9
  import { PositionDirection } from '.';
10
10
  export declare class ClearingHouseUser {
@@ -12,6 +12,7 @@ export declare class ClearingHouseUser {
12
12
  authority: PublicKey;
13
13
  accountSubscriber: UserAccountSubscriber;
14
14
  userAccountPublicKey?: PublicKey;
15
+ userOrdersAccountPublicKey?: PublicKey;
15
16
  isSubscribed: boolean;
16
17
  eventEmitter: StrictEventEmitter<EventEmitter, UserAccountEvents>;
17
18
  static from(clearingHouse: ClearingHouse, authority: PublicKey): ClearingHouseUser;
@@ -28,6 +29,7 @@ export declare class ClearingHouseUser {
28
29
  unsubscribe(): Promise<void>;
29
30
  getUserAccount(): UserAccount;
30
31
  getUserPositionsAccount(): UserPositionsAccount;
32
+ getUserOrdersAccount(): UserOrdersAccount;
31
33
  /**
32
34
  * Gets the user's current position for a given market. If the user has no position returns undefined
33
35
  * @param marketIndex
@@ -35,7 +37,13 @@ export declare class ClearingHouseUser {
35
37
  */
36
38
  getUserPosition(marketIndex: BN): UserPosition | undefined;
37
39
  getEmptyPosition(marketIndex: BN): UserPosition;
40
+ /**
41
+ * @param orderId
42
+ * @returns Order
43
+ */
44
+ getOrder(orderId: BN): Order | undefined;
38
45
  getUserAccountPublicKey(): Promise<PublicKey>;
46
+ getUserOrdersAccountPublicKey(): Promise<PublicKey>;
39
47
  exists(): Promise<boolean>;
40
48
  /**
41
49
  * calculates Buying Power = FC * MAX_LEVERAGE
@@ -125,21 +133,6 @@ export declare class ClearingHouseUser {
125
133
  liquidationPriceAfterClose(positionMarketIndex: BN, closeQuoteAmount: BN): BN;
126
134
  /**
127
135
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
128
- *
129
- * To Calculate Max Quote Available:
130
- *
131
- * Case 1: SameSide
132
- * => Remaining quote to get to maxLeverage
133
- *
134
- * Case 2: NOT SameSide && currentLeverage <= maxLeverage
135
- * => Current opposite position x2 + remaining to get to maxLeverage
136
- *
137
- * Case 3: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition > maxLeverage
138
- * => strictly reduce current position size
139
- *
140
- * Case 4: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition < maxLeverage
141
- * => current position + remaining to get to maxLeverage
142
- *
143
136
  * @param marketIndex
144
137
  * @param tradeSide
145
138
  * @param userMaxLeverageSetting - leverage : Precision TEN_THOUSAND
@@ -166,5 +159,5 @@ export declare class ClearingHouseUser {
166
159
  * @returns positionValue : Precision QUOTE_PRECISION
167
160
  */
168
161
  private getTotalPositionValueExcludingMarket;
162
+ canFillOrder(order: Order): boolean;
169
163
  }
170
- //# sourceMappingURL=clearingHouseUser.d.ts.map
@@ -63,6 +63,9 @@ class ClearingHouseUser {
63
63
  getUserPositionsAccount() {
64
64
  return this.accountSubscriber.getUserPositionsAccount();
65
65
  }
66
+ getUserOrdersAccount() {
67
+ return this.accountSubscriber.getUserOrdersAccount();
68
+ }
66
69
  /**
67
70
  * Gets the user's current position for a given market. If the user has no position returns undefined
68
71
  * @param marketIndex
@@ -77,8 +80,16 @@ class ClearingHouseUser {
77
80
  lastCumulativeFundingRate: numericConstants_1.ZERO,
78
81
  marketIndex,
79
82
  quoteAssetAmount: numericConstants_1.ZERO,
83
+ openOrders: numericConstants_1.ZERO,
80
84
  };
81
85
  }
86
+ /**
87
+ * @param orderId
88
+ * @returns Order
89
+ */
90
+ getOrder(orderId) {
91
+ return this.getUserOrdersAccount().orders.find((order) => order.orderId.eq(orderId));
92
+ }
82
93
  getUserAccountPublicKey() {
83
94
  return __awaiter(this, void 0, void 0, function* () {
84
95
  if (this.userAccountPublicKey) {
@@ -88,6 +99,15 @@ class ClearingHouseUser {
88
99
  return this.userAccountPublicKey;
89
100
  });
90
101
  }
102
+ getUserOrdersAccountPublicKey() {
103
+ return __awaiter(this, void 0, void 0, function* () {
104
+ if (this.userOrdersAccountPublicKey) {
105
+ return this.userOrdersAccountPublicKey;
106
+ }
107
+ this.userOrdersAccountPublicKey = yield _1.getUserOrdersAccountPublicKey(this.clearingHouse.program.programId, this.authority);
108
+ return this.userOrdersAccountPublicKey;
109
+ });
110
+ }
91
111
  exists() {
92
112
  return __awaiter(this, void 0, void 0, function* () {
93
113
  const userAccountPublicKey = yield this.getUserAccountPublicKey();
@@ -313,6 +333,7 @@ class ClearingHouseUser {
313
333
  baseAssetAmount: currentMarketPositionBaseSize.add(positionBaseSizeChange),
314
334
  lastCumulativeFundingRate: new bn_js_1.default(0),
315
335
  quoteAssetAmount: new bn_js_1.default(0),
336
+ openOrders: new bn_js_1.default(0),
316
337
  };
317
338
  const market = this.clearingHouse.getMarket(proposedMarketPosition.marketIndex);
318
339
  const proposedMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, proposedMarketPosition);
@@ -373,14 +394,14 @@ class ClearingHouseUser {
373
394
  liquidationPrice(targetMarket, positionBaseSizeChange = numericConstants_1.ZERO, partial = false) {
374
395
  // solves formula for example calc below
375
396
  /* example: assume BTC price is $40k (examine 10% up/down)
376
-
377
- if 10k deposit and levered 10x short BTC => BTC up $400 means:
378
- 1. higher base_asset_value (+$4k)
379
- 2. lower collateral (-$4k)
380
- 3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
381
-
382
- for 10x long, BTC down $400:
383
- 3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
397
+
398
+ if 10k deposit and levered 10x short BTC => BTC up $400 means:
399
+ 1. higher base_asset_value (+$4k)
400
+ 2. lower collateral (-$4k)
401
+ 3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
402
+
403
+ for 10x long, BTC down $400:
404
+ 3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
384
405
  const tc = this.getTotalCollateral();
385
406
  const tpv = this.getTotalPositionValue();
386
407
  const partialLev = 16;
@@ -398,6 +419,7 @@ class ClearingHouseUser {
398
419
  baseAssetAmount: proposedBaseAssetAmount,
399
420
  lastCumulativeFundingRate: currentMarketPosition.lastCumulativeFundingRate,
400
421
  quoteAssetAmount: new bn_js_1.default(0),
422
+ openOrders: new bn_js_1.default(0),
401
423
  };
402
424
  const market = this.clearingHouse.getMarket(proposedMarketPosition.marketIndex);
403
425
  const proposedMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, proposedMarketPosition);
@@ -474,42 +496,32 @@ class ClearingHouseUser {
474
496
  }
475
497
  /**
476
498
  * Get the maximum trade size for a given market, taking into account the user's current leverage, positions, collateral, etc.
477
- *
478
- * To Calculate Max Quote Available:
479
- *
480
- * Case 1: SameSide
481
- * => Remaining quote to get to maxLeverage
482
- *
483
- * Case 2: NOT SameSide && currentLeverage <= maxLeverage
484
- * => Current opposite position x2 + remaining to get to maxLeverage
485
- *
486
- * Case 3: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition > maxLeverage
487
- * => strictly reduce current position size
488
- *
489
- * Case 4: NOT SameSide && currentLeverage > maxLeverage && otherPositions - currentPosition < maxLeverage
490
- * => current position + remaining to get to maxLeverage
491
- *
492
499
  * @param marketIndex
493
500
  * @param tradeSide
494
501
  * @param userMaxLeverageSetting - leverage : Precision TEN_THOUSAND
495
502
  * @returns tradeSizeAllowed : Precision QUOTE_PRECISION
496
503
  */
497
504
  getMaxTradeSizeUSDC(targetMarketIndex, tradeSide, userMaxLeverageSetting) {
505
+ // inline function which get's the current position size on the opposite side of the target trade
506
+ const getOppositePositionValueUSDC = () => {
507
+ if (!currentPosition)
508
+ return numericConstants_1.ZERO;
509
+ const side = tradeSide === _1.PositionDirection.SHORT ? 'short' : 'long';
510
+ if (side === 'long' && (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())) {
511
+ return this.getPositionValue(targetMarketIndex);
512
+ }
513
+ else if (side === 'short' &&
514
+ !(currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())) {
515
+ return this.getPositionValue(targetMarketIndex);
516
+ }
517
+ return numericConstants_1.ZERO;
518
+ };
498
519
  const currentPosition = this.getUserPosition(targetMarketIndex) ||
499
520
  this.getEmptyPosition(targetMarketIndex);
500
- const targetSide = tradeSide === _1.PositionDirection.SHORT ? 'short' : 'long';
501
- const currentPositionSide = (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())
502
- ? 'short'
503
- : 'long';
504
- const targettingSameSide = !currentPosition
505
- ? true
506
- : targetSide === currentPositionSide;
507
- // add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
508
- const oppositeSizeValueUSDC = targettingSameSide
509
- ? numericConstants_1.ZERO
510
- : this.getPositionValue(targetMarketIndex);
511
521
  // get current leverage
512
522
  const currentLeverage = this.getLeverage();
523
+ // remaining leverage
524
+ // let remainingLeverage = userMaxLeverageSetting;
513
525
  const remainingLeverage = bn_js_1.default.max(userMaxLeverageSetting.sub(currentLeverage), numericConstants_1.ZERO);
514
526
  // get total collateral
515
527
  const totalCollateral = this.getTotalCollateral();
@@ -517,43 +529,9 @@ class ClearingHouseUser {
517
529
  let maxPositionSize = remainingLeverage
518
530
  .mul(totalCollateral)
519
531
  .div(numericConstants_1.TEN_THOUSAND);
520
- if (userMaxLeverageSetting.sub(currentLeverage).gte(numericConstants_1.ZERO)) {
521
- if (oppositeSizeValueUSDC.eq(numericConstants_1.ZERO)) {
522
- // case 1 : Regular trade where current total position less than max, and no opposite position to account for
523
- // do nothing
524
- }
525
- else {
526
- // case 2 : trade where current total position less than max, but need to account for flipping the current position over to the other side
527
- maxPositionSize = maxPositionSize.add(oppositeSizeValueUSDC.mul(new bn_js_1.default(2)));
528
- }
529
- }
530
- else {
531
- // current leverage is greater than max leverage - can only reduce position size
532
- if (!targettingSameSide) {
533
- const currentPositionQuoteSize = this.getPositionValue(targetMarketIndex);
534
- const currentTotalQuoteSize = currentLeverage
535
- .mul(totalCollateral)
536
- .div(numericConstants_1.TEN_THOUSAND);
537
- const otherPositionsTotalQuoteSize = currentTotalQuoteSize.sub(currentPositionQuoteSize);
538
- const quoteValueOfMaxLeverage = userMaxLeverageSetting
539
- .mul(totalCollateral)
540
- .div(numericConstants_1.TEN_THOUSAND);
541
- if (otherPositionsTotalQuoteSize
542
- .sub(currentPositionQuoteSize)
543
- .gte(quoteValueOfMaxLeverage)) {
544
- // case 3: Can only reduce the current position because it will still be greater than max leverage
545
- maxPositionSize = currentPositionQuoteSize;
546
- }
547
- else {
548
- // case 4: Can reduce the position, and then take extra remaining quote to get to max leverage
549
- const allowedQuoteSizeAfterClosingCurrentPosition = quoteValueOfMaxLeverage.sub(otherPositionsTotalQuoteSize);
550
- maxPositionSize = currentPositionQuoteSize.add(allowedQuoteSizeAfterClosingCurrentPosition);
551
- }
552
- }
553
- else {
554
- // do nothing if targetting same side
555
- }
556
- }
532
+ // add any position we have on the opposite side of the current trade, because we can "flip" the size of this position without taking any extra leverage.
533
+ const oppositeSizeValueUSDC = getOppositePositionValueUSDC();
534
+ maxPositionSize = maxPositionSize.add(oppositeSizeValueUSDC.mul(new bn_js_1.default(2)));
557
535
  // subtract oneMillionth of maxPositionSize
558
536
  // => to avoid rounding errors when taking max leverage
559
537
  const oneMilli = maxPositionSize.div(numericConstants_1.QUOTE_PRECISION);
@@ -582,18 +560,12 @@ class ClearingHouseUser {
582
560
  .add(tradeQuoteAmount)
583
561
  .abs();
584
562
  const totalPositionAfterTradeExcludingTargetMarket = this.getTotalPositionValueExcludingMarket(targetMarketIndex);
585
- const totalCollateral = this.getTotalCollateral();
586
- if (totalCollateral.gt(numericConstants_1.ZERO)) {
587
- const newLeverage = currentMarketPositionAfterTrade
588
- .add(totalPositionAfterTradeExcludingTargetMarket)
589
- .abs()
590
- .mul(numericConstants_1.TEN_THOUSAND)
591
- .div(totalCollateral);
592
- return newLeverage;
593
- }
594
- else {
595
- return new bn_js_1.default(0);
596
- }
563
+ const newLeverage = currentMarketPositionAfterTrade
564
+ .add(totalPositionAfterTradeExcludingTargetMarket)
565
+ .abs()
566
+ .mul(numericConstants_1.TEN_THOUSAND)
567
+ .div(this.getTotalCollateral());
568
+ return newLeverage;
597
569
  }
598
570
  /**
599
571
  * Calculates how much fee will be taken for a given sized trade
@@ -616,9 +588,51 @@ class ClearingHouseUser {
616
588
  this.getEmptyPosition(marketToIgnore);
617
589
  let currentMarketPositionValueUSDC = numericConstants_1.ZERO;
618
590
  if (currentMarketPosition) {
619
- currentMarketPositionValueUSDC = this.getPositionValue(marketToIgnore);
591
+ const market = this.clearingHouse.getMarket(currentMarketPosition.marketIndex);
592
+ currentMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, currentMarketPosition);
620
593
  }
621
594
  return this.getTotalPositionValue().sub(currentMarketPositionValueUSDC);
622
595
  }
596
+ canFillOrder(order) {
597
+ const userAccount = this.getUserAccount();
598
+ const userPositionsAccount = this.getUserPositionsAccount();
599
+ const userPosition = this.getUserPosition(order.marketIndex);
600
+ const market = this.clearingHouse.getMarket(order.marketIndex);
601
+ if (position_1.isEmptyPosition(userPosition)) {
602
+ return false;
603
+ }
604
+ const newState = _1.calculateNewStateAfterOrder(userAccount, userPosition, market, order);
605
+ if (newState === null) {
606
+ return false;
607
+ }
608
+ const [userAccountAfter, userPositionAfter, marketAfter] = newState;
609
+ const totalPositionValue = userPositionsAccount.positions.reduce((positionValue, marketPosition) => {
610
+ let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
611
+ if (marketPosition.marketIndex.eq(order.marketIndex)) {
612
+ market = marketAfter;
613
+ marketPosition = userPositionAfter;
614
+ }
615
+ return positionValue.add(_1.calculateBaseAssetValue(market, marketPosition));
616
+ }, numericConstants_1.ZERO);
617
+ if (totalPositionValue.eq(numericConstants_1.ZERO)) {
618
+ return true;
619
+ }
620
+ const unrealizedPnL = userPositionsAccount.positions.reduce((pnl, marketPosition) => {
621
+ let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
622
+ pnl = pnl.add(_1.calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION));
623
+ if (marketPosition.marketIndex.eq(order.marketIndex)) {
624
+ market = marketAfter;
625
+ marketPosition = userPositionAfter;
626
+ }
627
+ // update
628
+ return pnl.add(_1.calculatePositionPNL(market, marketPosition, false));
629
+ }, numericConstants_1.ZERO);
630
+ const totalCollateral = userAccountAfter.collateral.add(unrealizedPnL);
631
+ const marginRatioAfter = totalCollateral
632
+ .mul(numericConstants_1.TEN_THOUSAND)
633
+ .div(totalPositionValue);
634
+ const marginRatioInitial = this.clearingHouse.getStateAccount().marginRatioInitial;
635
+ return marginRatioAfter.gte(marginRatioInitial);
636
+ }
623
637
  }
624
638
  exports.ClearingHouseUser = ClearingHouseUser;
package/lib/config.d.ts CHANGED
@@ -21,4 +21,3 @@ export declare const initialize: (props: {
21
21
  overrideEnv?: Partial<DriftConfig>;
22
22
  }) => DriftConfig;
23
23
  export {};
24
- //# sourceMappingURL=config.d.ts.map
package/lib/config.js CHANGED
@@ -5,7 +5,7 @@ exports.configs = {
5
5
  devnet: {
6
6
  ENV: 'devnet',
7
7
  PYTH_ORACLE_MAPPING_ADDRESS: 'BmA9Z6FjioHJPpjT39QazZyhDRUdZy2ezwx4GiDdE2u2',
8
- CLEARING_HOUSE_PROGRAM_ID: 'AsW7LnXB9UA1uec9wi9MctYTgTz7YH9snhxd16GsFaGX',
8
+ CLEARING_HOUSE_PROGRAM_ID: 'HiZ8CnfEE9LrBZTfc8hBneWrPg1Cbsn8Wdy6SPLfae9V',
9
9
  USDC_MINT_ADDRESS: '8zGuJQqwhZafTah7Uc7Z4tXRnguqkn5KLFAP8oV6PHe2',
10
10
  },
11
11
  'mainnet-beta': {
@@ -9,4 +9,3 @@ declare type Market = {
9
9
  };
10
10
  export declare const Markets: Market[];
11
11
  export {};
12
- //# sourceMappingURL=markets.d.ts.map