@drift-labs/sdk 0.1.18-master.8 → 0.1.18-orders.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 (134) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +32 -0
  2. package/lib/accounts/bulkAccountLoader.js +156 -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 +133 -0
  11. package/lib/accounts/types.d.ts +34 -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 +0 -1
  15. package/lib/accounts/{defaultClearingHouseAccountSubscriber.d.ts → webSocketClearingHouseAccountSubscriber.d.ts} +8 -3
  16. package/lib/accounts/{defaultClearingHouseAccountSubscriber.js → webSocketClearingHouseAccountSubscriber.js} +30 -4
  17. package/lib/accounts/{defaultUserAccountSubscriber.d.ts → webSocketUserAccountSubscriber.d.ts} +6 -3
  18. package/lib/accounts/{defaultUserAccountSubscriber.js → webSocketUserAccountSubscriber.js} +16 -4
  19. package/lib/addresses.d.ts +4 -1
  20. package/lib/addresses.js +28 -1
  21. package/lib/admin.d.ts +11 -4
  22. package/lib/admin.js +71 -17
  23. package/lib/assert/assert.d.ts +0 -1
  24. package/lib/clearingHouse.d.ts +35 -4
  25. package/lib/clearingHouse.js +294 -23
  26. package/lib/clearingHouseUser.d.ts +19 -18
  27. package/lib/clearingHouseUser.js +129 -101
  28. package/lib/config.d.ts +0 -1
  29. package/lib/config.js +1 -1
  30. package/lib/constants/markets.d.ts +0 -1
  31. package/lib/constants/numericConstants.d.ts +0 -1
  32. package/lib/examples/makeTradeExample.d.ts +0 -1
  33. package/lib/examples/makeTradeExample.js +6 -6
  34. package/lib/factory/clearingHouse.d.ts +25 -0
  35. package/lib/factory/clearingHouse.js +64 -0
  36. package/lib/factory/clearingHouseUser.d.ts +19 -0
  37. package/lib/factory/clearingHouseUser.js +34 -0
  38. package/lib/idl/clearing_house.json +1077 -54
  39. package/lib/index.d.ts +11 -3
  40. package/lib/index.js +12 -2
  41. package/lib/math/amm.d.ts +1 -1
  42. package/lib/math/amm.js +38 -15
  43. package/lib/math/conversion.d.ts +0 -1
  44. package/lib/math/conversion.js +1 -1
  45. package/lib/math/funding.d.ts +0 -1
  46. package/lib/math/funding.js +1 -1
  47. package/lib/math/insuranceFund.d.ts +0 -1
  48. package/lib/math/market.d.ts +2 -2
  49. package/lib/math/market.js +12 -2
  50. package/lib/math/orders.d.ts +3 -0
  51. package/lib/math/orders.js +30 -0
  52. package/lib/math/position.d.ts +4 -2
  53. package/lib/math/position.js +19 -5
  54. package/lib/math/trade.d.ts +0 -1
  55. package/lib/math/trade.js +16 -16
  56. package/lib/math/utils.d.ts +2 -3
  57. package/lib/math/utils.js +6 -3
  58. package/lib/mockUSDCFaucet.d.ts +0 -1
  59. package/lib/orderParams.d.ts +7 -0
  60. package/lib/orderParams.js +108 -0
  61. package/lib/orders.d.ts +5 -0
  62. package/lib/orders.js +136 -0
  63. package/lib/pythClient.d.ts +0 -1
  64. package/lib/pythClient.js +1 -1
  65. package/lib/token/index.d.ts +3 -0
  66. package/lib/token/index.js +38 -0
  67. package/lib/tx/defaultTxSender.d.ts +0 -1
  68. package/lib/tx/types.d.ts +0 -1
  69. package/lib/tx/utils.d.ts +0 -1
  70. package/lib/types.d.ts +144 -2
  71. package/lib/types.js +36 -1
  72. package/lib/util/computeUnits.d.ts +0 -1
  73. package/lib/util/tps.d.ts +0 -1
  74. package/lib/wallet.d.ts +0 -1
  75. package/package.json +3 -3
  76. package/src/accounts/bulkAccountLoader.ts +195 -0
  77. package/src/accounts/bulkUserSubscription.ts +28 -0
  78. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +326 -0
  79. package/src/accounts/pollingTokenAccountSubscriber.ts +99 -0
  80. package/src/accounts/pollingUserAccountSubscriber.ts +186 -0
  81. package/src/accounts/types.ts +43 -1
  82. package/src/accounts/utils.ts +3 -0
  83. package/src/accounts/{defaultClearingHouseAccountSubscriber.ts → webSocketClearingHouseAccountSubscriber.ts} +51 -1
  84. package/src/accounts/{defaultUserAccountSubscriber.ts → webSocketUserAccountSubscriber.ts} +33 -3
  85. package/src/addresses.ts +37 -0
  86. package/src/admin.ts +111 -24
  87. package/src/clearingHouse.ts +399 -22
  88. package/src/clearingHouseUser.ts +179 -107
  89. package/src/config.ts +1 -1
  90. package/src/factory/clearingHouse.ts +125 -0
  91. package/src/factory/clearingHouseUser.ts +73 -0
  92. package/src/idl/clearing_house.json +1077 -54
  93. package/src/index.ts +11 -2
  94. package/src/math/amm.ts +47 -14
  95. package/src/math/market.ts +28 -2
  96. package/src/math/orders.ts +39 -0
  97. package/src/math/position.ts +23 -3
  98. package/src/math/utils.ts +1 -1
  99. package/src/orderParams.ts +151 -0
  100. package/src/orders.ts +230 -0
  101. package/src/token/index.ts +37 -0
  102. package/src/types.ts +128 -1
  103. package/tsconfig.json +0 -1
  104. package/lib/accounts/defaultClearingHouseAccountSubscriber.d.ts.map +0 -1
  105. package/lib/accounts/defaultUserAccountSubscriber.d.ts.map +0 -1
  106. package/lib/accounts/types.d.ts.map +0 -1
  107. package/lib/accounts/webSocketAccountSubscriber.d.ts.map +0 -1
  108. package/lib/addresses.d.ts.map +0 -1
  109. package/lib/admin.d.ts.map +0 -1
  110. package/lib/assert/assert.d.ts.map +0 -1
  111. package/lib/clearingHouse.d.ts.map +0 -1
  112. package/lib/clearingHouseUser.d.ts.map +0 -1
  113. package/lib/config.d.ts.map +0 -1
  114. package/lib/constants/markets.d.ts.map +0 -1
  115. package/lib/constants/numericConstants.d.ts.map +0 -1
  116. package/lib/examples/makeTradeExample.d.ts.map +0 -1
  117. package/lib/index.d.ts.map +0 -1
  118. package/lib/math/amm.d.ts.map +0 -1
  119. package/lib/math/conversion.d.ts.map +0 -1
  120. package/lib/math/funding.d.ts.map +0 -1
  121. package/lib/math/insuranceFund.d.ts.map +0 -1
  122. package/lib/math/market.d.ts.map +0 -1
  123. package/lib/math/position.d.ts.map +0 -1
  124. package/lib/math/trade.d.ts.map +0 -1
  125. package/lib/math/utils.d.ts.map +0 -1
  126. package/lib/mockUSDCFaucet.d.ts.map +0 -1
  127. package/lib/pythClient.d.ts.map +0 -1
  128. package/lib/tx/defaultTxSender.d.ts.map +0 -1
  129. package/lib/tx/types.d.ts.map +0 -1
  130. package/lib/tx/utils.d.ts.map +0 -1
  131. package/lib/types.d.ts.map +0 -1
  132. package/lib/util/computeUnits.d.ts.map +0 -1
  133. package/lib/util/tps.d.ts.map +0 -1
  134. package/lib/wallet.d.ts.map +0 -1
@@ -16,20 +16,34 @@ exports.ClearingHouseUser = void 0;
16
16
  const bn_js_1 = __importDefault(require("bn.js"));
17
17
  const position_1 = require("./math/position");
18
18
  const numericConstants_1 = require("./constants/numericConstants");
19
- const defaultUserAccountSubscriber_1 = require("./accounts/defaultUserAccountSubscriber");
20
19
  const _1 = require(".");
21
20
  const addresses_1 = require("./addresses");
21
+ const clearingHouseUser_1 = require("./factory/clearingHouseUser");
22
22
  class ClearingHouseUser {
23
23
  constructor(clearingHouse, authority, accountSubscriber) {
24
- this.isSubscribed = false;
24
+ this._isSubscribed = false;
25
25
  this.clearingHouse = clearingHouse;
26
26
  this.authority = authority;
27
27
  this.accountSubscriber = accountSubscriber;
28
28
  this.eventEmitter = this.accountSubscriber.eventEmitter;
29
29
  }
30
+ get isSubscribed() {
31
+ return this._isSubscribed && this.accountSubscriber.isSubscribed;
32
+ }
33
+ set isSubscribed(val) {
34
+ this._isSubscribed = val;
35
+ }
36
+ /**
37
+ * @deprecated You should use getClearingHouseUser factory method instead
38
+ * @param clearingHouse
39
+ * @param authority
40
+ * @returns
41
+ */
30
42
  static from(clearingHouse, authority) {
31
- const accountSubscriber = new defaultUserAccountSubscriber_1.DefaultUserAccountSubscriber(clearingHouse.program, authority);
32
- return new ClearingHouseUser(clearingHouse, authority, accountSubscriber);
43
+ if (clearingHouse.accountSubscriber.type !== 'websocket')
44
+ throw 'This method only works for clearing houses with a websocket account listener. Try using the getClearingHouseUser factory method to initialize a ClearingHouseUser instead';
45
+ const config = clearingHouseUser_1.getWebSocketClearingHouseUserConfig(clearingHouse, authority);
46
+ return clearingHouseUser_1.getClearingHouseUser(config);
33
47
  }
34
48
  /**
35
49
  * Subscribe to ClearingHouseUser state accounts
@@ -63,6 +77,9 @@ class ClearingHouseUser {
63
77
  getUserPositionsAccount() {
64
78
  return this.accountSubscriber.getUserPositionsAccount();
65
79
  }
80
+ getUserOrdersAccount() {
81
+ return this.accountSubscriber.getUserOrdersAccount();
82
+ }
66
83
  /**
67
84
  * Gets the user's current position for a given market. If the user has no position returns undefined
68
85
  * @param marketIndex
@@ -77,17 +94,34 @@ class ClearingHouseUser {
77
94
  lastCumulativeFundingRate: numericConstants_1.ZERO,
78
95
  marketIndex,
79
96
  quoteAssetAmount: numericConstants_1.ZERO,
97
+ openOrders: numericConstants_1.ZERO,
80
98
  };
81
99
  }
100
+ /**
101
+ * @param orderId
102
+ * @returns Order
103
+ */
104
+ getOrder(orderId) {
105
+ return this.getUserOrdersAccount().orders.find((order) => order.orderId.eq(orderId));
106
+ }
82
107
  getUserAccountPublicKey() {
83
108
  return __awaiter(this, void 0, void 0, function* () {
84
109
  if (this.userAccountPublicKey) {
85
110
  return this.userAccountPublicKey;
86
111
  }
87
- this.userAccountPublicKey = yield (0, addresses_1.getUserAccountPublicKey)(this.clearingHouse.program.programId, this.authority);
112
+ this.userAccountPublicKey = yield addresses_1.getUserAccountPublicKey(this.clearingHouse.program.programId, this.authority);
88
113
  return this.userAccountPublicKey;
89
114
  });
90
115
  }
116
+ getUserOrdersAccountPublicKey() {
117
+ return __awaiter(this, void 0, void 0, function* () {
118
+ if (this.userOrdersAccountPublicKey) {
119
+ return this.userOrdersAccountPublicKey;
120
+ }
121
+ this.userOrdersAccountPublicKey = yield _1.getUserOrdersAccountPublicKey(this.clearingHouse.program.programId, yield this.getUserAccountPublicKey());
122
+ return this.userOrdersAccountPublicKey;
123
+ });
124
+ }
91
125
  exists() {
92
126
  return __awaiter(this, void 0, void 0, function* () {
93
127
  const userAccountPublicKey = yield this.getUserAccountPublicKey();
@@ -122,7 +156,7 @@ class ClearingHouseUser {
122
156
  .positions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
123
157
  .reduce((pnl, marketPosition) => {
124
158
  const market = this.clearingHouse.getMarket(marketPosition.marketIndex);
125
- return pnl.add((0, _1.calculatePositionPNL)(market, marketPosition, withFunding));
159
+ return pnl.add(_1.calculatePositionPNL(market, marketPosition, withFunding));
126
160
  }, numericConstants_1.ZERO);
127
161
  }
128
162
  /**
@@ -134,7 +168,7 @@ class ClearingHouseUser {
134
168
  .positions.filter((pos) => marketIndex ? pos.marketIndex === marketIndex : true)
135
169
  .reduce((pnl, marketPosition) => {
136
170
  const market = this.clearingHouse.getMarket(marketPosition.marketIndex);
137
- return pnl.add((0, _1.calculatePositionFundingPNL)(market, marketPosition));
171
+ return pnl.add(_1.calculatePositionFundingPNL(market, marketPosition));
138
172
  }, numericConstants_1.ZERO);
139
173
  }
140
174
  /**
@@ -152,7 +186,7 @@ class ClearingHouseUser {
152
186
  getTotalPositionValue() {
153
187
  return this.getUserPositionsAccount().positions.reduce((positionValue, marketPosition) => {
154
188
  const market = this.clearingHouse.getMarket(marketPosition.marketIndex);
155
- return positionValue.add((0, _1.calculateBaseAssetValue)(market, marketPosition));
189
+ return positionValue.add(_1.calculateBaseAssetValue(market, marketPosition));
156
190
  }, numericConstants_1.ZERO);
157
191
  }
158
192
  /**
@@ -162,7 +196,7 @@ class ClearingHouseUser {
162
196
  getPositionValue(marketIndex) {
163
197
  const userPosition = this.getUserPosition(marketIndex) || this.getEmptyPosition(marketIndex);
164
198
  const market = this.clearingHouse.getMarket(userPosition.marketIndex);
165
- return (0, _1.calculateBaseAssetValue)(market, userPosition);
199
+ return _1.calculateBaseAssetValue(market, userPosition);
166
200
  }
167
201
  getPositionSide(currentPosition) {
168
202
  if (currentPosition.baseAssetAmount.gt(numericConstants_1.ZERO)) {
@@ -181,10 +215,10 @@ class ClearingHouseUser {
181
215
  */
182
216
  getPositionEstimatedExitPriceAndPnl(position, amountToClose) {
183
217
  const market = this.clearingHouse.getMarket(position.marketIndex);
184
- const entryPrice = (0, position_1.calculateEntryPrice)(position);
218
+ const entryPrice = position_1.calculateEntryPrice(position);
185
219
  if (amountToClose) {
186
220
  if (amountToClose.eq(numericConstants_1.ZERO)) {
187
- return [(0, _1.calculateMarkPrice)(market), numericConstants_1.ZERO];
221
+ return [_1.calculateMarkPrice(market), numericConstants_1.ZERO];
188
222
  }
189
223
  position = {
190
224
  baseAssetAmount: amountToClose,
@@ -193,7 +227,7 @@ class ClearingHouseUser {
193
227
  quoteAssetAmount: position.quoteAssetAmount,
194
228
  };
195
229
  }
196
- const baseAssetValue = (0, _1.calculateBaseAssetValue)(market, position);
230
+ const baseAssetValue = _1.calculateBaseAssetValue(market, position);
197
231
  if (position.baseAssetAmount.eq(numericConstants_1.ZERO)) {
198
232
  return [numericConstants_1.ZERO, numericConstants_1.ZERO];
199
233
  }
@@ -300,7 +334,7 @@ class ClearingHouseUser {
300
334
 
301
335
  for 10x long, BTC down $400:
302
336
  3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
303
- const currentPrice = (0, _1.calculateMarkPrice)(this.clearingHouse.getMarket(targetMarket.marketIndex));
337
+ const currentPrice = _1.calculateMarkPrice(this.clearingHouse.getMarket(targetMarket.marketIndex));
304
338
  const totalCollateralUSDC = this.getTotalCollateral();
305
339
  // calculate the total position value ignoring any value from the target market of the trade
306
340
  const totalCurrentPositionValueIgnoringTargetUSDC = this.getTotalPositionValueExcludingMarket(targetMarket.marketIndex);
@@ -313,9 +347,10 @@ class ClearingHouseUser {
313
347
  baseAssetAmount: currentMarketPositionBaseSize.add(positionBaseSizeChange),
314
348
  lastCumulativeFundingRate: new bn_js_1.default(0),
315
349
  quoteAssetAmount: new bn_js_1.default(0),
350
+ openOrders: new bn_js_1.default(0),
316
351
  };
317
352
  const market = this.clearingHouse.getMarket(proposedMarketPosition.marketIndex);
318
- const proposedMarketPositionValueUSDC = (0, _1.calculateBaseAssetValue)(market, proposedMarketPosition);
353
+ const proposedMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, proposedMarketPosition);
319
354
  // total position value after trade
320
355
  const targetTotalPositionValueUSDC = totalCurrentPositionValueIgnoringTargetUSDC.add(proposedMarketPositionValueUSDC);
321
356
  let totalFreeCollateralUSDC = this.getTotalCollateral().sub(this.getTotalPositionValue()
@@ -373,14 +408,14 @@ class ClearingHouseUser {
373
408
  liquidationPrice(targetMarket, positionBaseSizeChange = numericConstants_1.ZERO, partial = false) {
374
409
  // solves formula for example calc below
375
410
  /* 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 */
411
+
412
+ if 10k deposit and levered 10x short BTC => BTC up $400 means:
413
+ 1. higher base_asset_value (+$4k)
414
+ 2. lower collateral (-$4k)
415
+ 3. (10k - 4k)/(100k + 4k) => 6k/104k => .0576
416
+
417
+ for 10x long, BTC down $400:
418
+ 3. (10k - 4k) / (100k - 4k) = 6k/96k => .0625 */
384
419
  const tc = this.getTotalCollateral();
385
420
  const tpv = this.getTotalPositionValue();
386
421
  const partialLev = 16;
@@ -398,9 +433,10 @@ class ClearingHouseUser {
398
433
  baseAssetAmount: proposedBaseAssetAmount,
399
434
  lastCumulativeFundingRate: currentMarketPosition.lastCumulativeFundingRate,
400
435
  quoteAssetAmount: new bn_js_1.default(0),
436
+ openOrders: new bn_js_1.default(0),
401
437
  };
402
438
  const market = this.clearingHouse.getMarket(proposedMarketPosition.marketIndex);
403
- const proposedMarketPositionValueUSDC = (0, _1.calculateBaseAssetValue)(market, proposedMarketPosition);
439
+ const proposedMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, proposedMarketPosition);
404
440
  // total position value after trade
405
441
  const targetTotalPositionValueUSDC = totalCurrentPositionValueIgnoringTargetUSDC.add(proposedMarketPositionValueUSDC);
406
442
  let totalFreeCollateralUSDC = tc.sub(totalCurrentPositionValueIgnoringTargetUSDC
@@ -428,13 +464,13 @@ class ClearingHouseUser {
428
464
  }
429
465
  let currentPrice;
430
466
  if (positionBaseSizeChange.eq(numericConstants_1.ZERO)) {
431
- currentPrice = (0, _1.calculateMarkPrice)(this.clearingHouse.getMarket(targetMarket.marketIndex));
467
+ currentPrice = _1.calculateMarkPrice(this.clearingHouse.getMarket(targetMarket.marketIndex));
432
468
  }
433
469
  else {
434
470
  const direction = positionBaseSizeChange.gt(numericConstants_1.ZERO)
435
471
  ? _1.PositionDirection.LONG
436
472
  : _1.PositionDirection.SHORT;
437
- currentPrice = (0, _1.calculateTradeSlippage)(direction, positionBaseSizeChange.abs(), this.clearingHouse.getMarket(targetMarket.marketIndex), 'base')[3]; // newPrice after swap
473
+ currentPrice = _1.calculateTradeSlippage(direction, positionBaseSizeChange.abs(), this.clearingHouse.getMarket(targetMarket.marketIndex), 'base')[3]; // newPrice after swap
438
474
  }
439
475
  // if the position value after the trade is less than total collateral, there is no liq price
440
476
  if (targetTotalPositionValueUSDC.lte(totalFreeCollateralUSDC) &&
@@ -474,42 +510,32 @@ class ClearingHouseUser {
474
510
  }
475
511
  /**
476
512
  * 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
513
  * @param marketIndex
493
514
  * @param tradeSide
494
515
  * @param userMaxLeverageSetting - leverage : Precision TEN_THOUSAND
495
516
  * @returns tradeSizeAllowed : Precision QUOTE_PRECISION
496
517
  */
497
518
  getMaxTradeSizeUSDC(targetMarketIndex, tradeSide, userMaxLeverageSetting) {
519
+ // inline function which get's the current position size on the opposite side of the target trade
520
+ const getOppositePositionValueUSDC = () => {
521
+ if (!currentPosition)
522
+ return numericConstants_1.ZERO;
523
+ const side = tradeSide === _1.PositionDirection.SHORT ? 'short' : 'long';
524
+ if (side === 'long' && (currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())) {
525
+ return this.getPositionValue(targetMarketIndex);
526
+ }
527
+ else if (side === 'short' &&
528
+ !(currentPosition === null || currentPosition === void 0 ? void 0 : currentPosition.baseAssetAmount.isNeg())) {
529
+ return this.getPositionValue(targetMarketIndex);
530
+ }
531
+ return numericConstants_1.ZERO;
532
+ };
498
533
  const currentPosition = this.getUserPosition(targetMarketIndex) ||
499
534
  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
535
  // get current leverage
512
536
  const currentLeverage = this.getLeverage();
537
+ // remaining leverage
538
+ // let remainingLeverage = userMaxLeverageSetting;
513
539
  const remainingLeverage = bn_js_1.default.max(userMaxLeverageSetting.sub(currentLeverage), numericConstants_1.ZERO);
514
540
  // get total collateral
515
541
  const totalCollateral = this.getTotalCollateral();
@@ -517,43 +543,9 @@ class ClearingHouseUser {
517
543
  let maxPositionSize = remainingLeverage
518
544
  .mul(totalCollateral)
519
545
  .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
- }
546
+ // 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.
547
+ const oppositeSizeValueUSDC = getOppositePositionValueUSDC();
548
+ maxPositionSize = maxPositionSize.add(oppositeSizeValueUSDC.mul(new bn_js_1.default(2)));
557
549
  // subtract oneMillionth of maxPositionSize
558
550
  // => to avoid rounding errors when taking max leverage
559
551
  const oneMilli = maxPositionSize.div(numericConstants_1.QUOTE_PRECISION);
@@ -582,18 +574,12 @@ class ClearingHouseUser {
582
574
  .add(tradeQuoteAmount)
583
575
  .abs();
584
576
  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
- }
577
+ const newLeverage = currentMarketPositionAfterTrade
578
+ .add(totalPositionAfterTradeExcludingTargetMarket)
579
+ .abs()
580
+ .mul(numericConstants_1.TEN_THOUSAND)
581
+ .div(this.getTotalCollateral());
582
+ return newLeverage;
597
583
  }
598
584
  /**
599
585
  * Calculates how much fee will be taken for a given sized trade
@@ -616,9 +602,51 @@ class ClearingHouseUser {
616
602
  this.getEmptyPosition(marketToIgnore);
617
603
  let currentMarketPositionValueUSDC = numericConstants_1.ZERO;
618
604
  if (currentMarketPosition) {
619
- currentMarketPositionValueUSDC = this.getPositionValue(marketToIgnore);
605
+ const market = this.clearingHouse.getMarket(currentMarketPosition.marketIndex);
606
+ currentMarketPositionValueUSDC = _1.calculateBaseAssetValue(market, currentMarketPosition);
620
607
  }
621
608
  return this.getTotalPositionValue().sub(currentMarketPositionValueUSDC);
622
609
  }
610
+ canFillOrder(order) {
611
+ const userAccount = this.getUserAccount();
612
+ const userPositionsAccount = this.getUserPositionsAccount();
613
+ const userPosition = this.getUserPosition(order.marketIndex);
614
+ const market = this.clearingHouse.getMarket(order.marketIndex);
615
+ if (position_1.isEmptyPosition(userPosition)) {
616
+ return false;
617
+ }
618
+ const newState = _1.calculateNewStateAfterOrder(userAccount, userPosition, market, order);
619
+ if (newState === null) {
620
+ return false;
621
+ }
622
+ const [userAccountAfter, userPositionAfter, marketAfter] = newState;
623
+ const totalPositionValue = userPositionsAccount.positions.reduce((positionValue, marketPosition) => {
624
+ let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
625
+ if (marketPosition.marketIndex.eq(order.marketIndex)) {
626
+ market = marketAfter;
627
+ marketPosition = userPositionAfter;
628
+ }
629
+ return positionValue.add(_1.calculateBaseAssetValue(market, marketPosition));
630
+ }, numericConstants_1.ZERO);
631
+ if (totalPositionValue.eq(numericConstants_1.ZERO)) {
632
+ return true;
633
+ }
634
+ const unrealizedPnL = userPositionsAccount.positions.reduce((pnl, marketPosition) => {
635
+ let market = this.clearingHouse.getMarket(marketPosition.marketIndex);
636
+ pnl = pnl.add(_1.calculatePositionFundingPNL(market, marketPosition).div(numericConstants_1.PRICE_TO_QUOTE_PRECISION));
637
+ if (marketPosition.marketIndex.eq(order.marketIndex)) {
638
+ market = marketAfter;
639
+ marketPosition = userPositionAfter;
640
+ }
641
+ // update
642
+ return pnl.add(_1.calculatePositionPNL(market, marketPosition, false));
643
+ }, numericConstants_1.ZERO);
644
+ const totalCollateral = userAccountAfter.collateral.add(unrealizedPnL);
645
+ const marginRatioAfter = totalCollateral
646
+ .mul(numericConstants_1.TEN_THOUSAND)
647
+ .div(totalPositionValue);
648
+ const marginRatioInitial = this.clearingHouse.getStateAccount().marginRatioInitial;
649
+ return marginRatioAfter.gte(marginRatioInitial);
650
+ }
623
651
  }
624
652
  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: '8mKouB1uzsoMAhAu4qAXCiu8KAfwH7nonpuYfTM21Xg2',
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
@@ -14,4 +14,3 @@ export declare const AMM_RESERVE_PRECISION: BN;
14
14
  export declare const AMM_TO_QUOTE_PRECISION_RATIO: BN;
15
15
  export declare const PRICE_TO_QUOTE_PRECISION: BN;
16
16
  export declare const AMM_TIMES_PEG_TO_QUOTE_PRECISION_RATIO: BN;
17
- //# sourceMappingURL=numericConstants.d.ts.map
@@ -1,3 +1,2 @@
1
1
  import { PublicKey } from '@solana/web3.js';
2
2
  export declare const getTokenAddress: (mintAddress: string, userPubKey: string) => Promise<PublicKey>;
3
- //# sourceMappingURL=makeTradeExample.d.ts.map
@@ -21,7 +21,7 @@ const getTokenAddress = (mintAddress, userPubKey) => {
21
21
  exports.getTokenAddress = getTokenAddress;
22
22
  const main = () => __awaiter(void 0, void 0, void 0, function* () {
23
23
  // Initialize Drift SDK
24
- const sdkConfig = (0, __2.initialize)({ env: 'devnet' });
24
+ const sdkConfig = __2.initialize({ env: 'devnet' });
25
25
  // Set up the Wallet and Provider
26
26
  const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
27
27
  const keypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(privateKey)));
@@ -35,7 +35,7 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
35
35
  const lamportsBalance = yield connection.getBalance(wallet.publicKey);
36
36
  console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
37
37
  // Misc. other things to set up
38
- const usdcTokenAddress = yield (0, exports.getTokenAddress)(sdkConfig.USDC_MINT_ADDRESS, wallet.publicKey.toString());
38
+ const usdcTokenAddress = yield exports.getTokenAddress(sdkConfig.USDC_MINT_ADDRESS, wallet.publicKey.toString());
39
39
  // Set up the Drift Clearing House
40
40
  const clearingHousePublicKey = new web3_js_1.PublicKey(sdkConfig.CLEARING_HOUSE_PROGRAM_ID);
41
41
  const clearingHouse = __2.ClearingHouse.from(connection, provider.wallet, clearingHousePublicKey);
@@ -47,18 +47,18 @@ const main = () => __awaiter(void 0, void 0, void 0, function* () {
47
47
  if (!userAccountExists) {
48
48
  //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
49
49
  const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
50
- yield clearingHouse.initializeUserAccountAndDepositCollateral(depositAmount, yield (0, exports.getTokenAddress)(usdcTokenAddress.toString(), wallet.publicKey.toString()));
50
+ yield clearingHouse.initializeUserAccountAndDepositCollateral(depositAmount, yield exports.getTokenAddress(usdcTokenAddress.toString(), wallet.publicKey.toString()));
51
51
  }
52
52
  yield user.subscribe();
53
53
  // Get current price
54
54
  const solMarketInfo = __2.Markets.find((market) => market.baseAssetSymbol === 'SOL');
55
- const currentMarketPrice = (0, __2.calculateMarkPrice)(clearingHouse.getMarket(solMarketInfo.marketIndex));
56
- const formattedPrice = (0, __2.convertToNumber)(currentMarketPrice, __2.QUOTE_PRECISION);
55
+ const currentMarketPrice = __2.calculateMarkPrice(clearingHouse.getMarket(solMarketInfo.marketIndex));
56
+ const formattedPrice = __2.convertToNumber(currentMarketPrice, __2.QUOTE_PRECISION);
57
57
  console.log(`Current Market Price is $${formattedPrice}`);
58
58
  // Estimate the slippage for a $5000 LONG trade
59
59
  const solMarketAccount = clearingHouse.getMarket(solMarketInfo.marketIndex);
60
60
  const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
61
- const slippage = (0, __2.convertToNumber)((0, __2.calculateTradeSlippage)(__2.PositionDirection.LONG, longAmount, solMarketAccount)[0], __2.MARK_PRICE_PRECISION);
61
+ const slippage = __2.convertToNumber(__2.calculateTradeSlippage(__2.PositionDirection.LONG, longAmount, solMarketAccount)[0], __2.MARK_PRICE_PRECISION);
62
62
  console.log(`Slippage for a $5000 LONG on the SOL market would be $${slippage}`);
63
63
  // Make a $5000 LONG trade
64
64
  yield clearingHouse.openPosition(__2.PositionDirection.LONG, longAmount, solMarketInfo.marketIndex);
@@ -0,0 +1,25 @@
1
+ import { ConfirmOptions, Connection, PublicKey } from '@solana/web3.js';
2
+ import { IWallet } from '../types';
3
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
4
+ import { TxSender } from '../tx/types';
5
+ import { ClearingHouse } from '../clearingHouse';
6
+ import { Admin } from '../admin';
7
+ export declare type ClearingHouseConfigType = 'websocket' | 'polling' | 'custom';
8
+ declare type BaseClearingHouseConfig = {
9
+ type: ClearingHouseConfigType;
10
+ connection: Connection;
11
+ wallet: IWallet;
12
+ programID: PublicKey;
13
+ opts?: ConfirmOptions;
14
+ txSender?: TxSender;
15
+ };
16
+ declare type WebSocketClearingHouseConfiguration = BaseClearingHouseConfig;
17
+ declare type PollingClearingHouseConfiguration = BaseClearingHouseConfig & {
18
+ accountLoader: BulkAccountLoader;
19
+ };
20
+ declare type ClearingHouseConfig = PollingClearingHouseConfiguration | WebSocketClearingHouseConfiguration;
21
+ export declare function getWebSocketClearingHouseConfig(connection: Connection, wallet: IWallet, programID: PublicKey, opts?: ConfirmOptions, txSender?: TxSender): WebSocketClearingHouseConfiguration;
22
+ export declare function getPollingClearingHouseConfig(connection: Connection, wallet: IWallet, programID: PublicKey, accountLoader: BulkAccountLoader, opts?: ConfirmOptions, txSender?: TxSender): PollingClearingHouseConfiguration;
23
+ export declare function getClearingHouse(config: ClearingHouseConfig): ClearingHouse;
24
+ export declare function getAdmin(config: ClearingHouseConfig): Admin;
25
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.getAdmin = exports.getClearingHouse = exports.getPollingClearingHouseConfig = exports.getWebSocketClearingHouseConfig = void 0;
7
+ const anchor_1 = require("@project-serum/anchor");
8
+ const clearingHouse_1 = require("../clearingHouse");
9
+ const clearing_house_json_1 = __importDefault(require("../idl/clearing_house.json"));
10
+ const webSocketClearingHouseAccountSubscriber_1 = require("../accounts/webSocketClearingHouseAccountSubscriber");
11
+ const defaultTxSender_1 = require("../tx/defaultTxSender");
12
+ const pollingClearingHouseAccountSubscriber_1 = require("../accounts/pollingClearingHouseAccountSubscriber");
13
+ const admin_1 = require("../admin");
14
+ function getWebSocketClearingHouseConfig(connection, wallet, programID, opts = anchor_1.Provider.defaultOptions(), txSender) {
15
+ return {
16
+ type: 'websocket',
17
+ connection,
18
+ wallet,
19
+ programID,
20
+ opts,
21
+ txSender,
22
+ };
23
+ }
24
+ exports.getWebSocketClearingHouseConfig = getWebSocketClearingHouseConfig;
25
+ function getPollingClearingHouseConfig(connection, wallet, programID, accountLoader, opts = anchor_1.Provider.defaultOptions(), txSender) {
26
+ return {
27
+ type: 'polling',
28
+ connection,
29
+ wallet,
30
+ programID,
31
+ accountLoader,
32
+ opts,
33
+ txSender,
34
+ };
35
+ }
36
+ exports.getPollingClearingHouseConfig = getPollingClearingHouseConfig;
37
+ function getClearingHouse(config) {
38
+ const provider = new anchor_1.Provider(config.connection, config.wallet, config.opts);
39
+ const program = new anchor_1.Program(clearing_house_json_1.default, config.programID, provider);
40
+ let accountSubscriber;
41
+ if (config.type === 'websocket') {
42
+ accountSubscriber = new webSocketClearingHouseAccountSubscriber_1.WebSocketClearingHouseAccountSubscriber(program);
43
+ }
44
+ else if (config.type === 'polling') {
45
+ accountSubscriber = new pollingClearingHouseAccountSubscriber_1.PollingClearingHouseAccountSubscriber(program, config.accountLoader);
46
+ }
47
+ const txSender = config.txSender || new defaultTxSender_1.DefaultTxSender(provider);
48
+ return new clearingHouse_1.ClearingHouse(config.connection, config.wallet, program, accountSubscriber, txSender, config.opts);
49
+ }
50
+ exports.getClearingHouse = getClearingHouse;
51
+ function getAdmin(config) {
52
+ const provider = new anchor_1.Provider(config.connection, config.wallet, config.opts);
53
+ const program = new anchor_1.Program(clearing_house_json_1.default, config.programID, provider);
54
+ let accountSubscriber;
55
+ if (config.type === 'websocket') {
56
+ accountSubscriber = new webSocketClearingHouseAccountSubscriber_1.WebSocketClearingHouseAccountSubscriber(program);
57
+ }
58
+ else if (config.type === 'polling') {
59
+ accountSubscriber = new pollingClearingHouseAccountSubscriber_1.PollingClearingHouseAccountSubscriber(program, config.accountLoader);
60
+ }
61
+ const txSender = config.txSender || new defaultTxSender_1.DefaultTxSender(provider);
62
+ return new admin_1.Admin(config.connection, config.wallet, program, accountSubscriber, txSender, config.opts);
63
+ }
64
+ exports.getAdmin = getAdmin;
@@ -0,0 +1,19 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ import { ClearingHouse } from '../clearingHouse';
3
+ import { BulkAccountLoader } from '../accounts/bulkAccountLoader';
4
+ import { ClearingHouseUser } from '../clearingHouseUser';
5
+ export declare type ClearingHouseUserConfigType = 'websocket' | 'polling' | 'custom';
6
+ declare type BaseClearingHouseUserConfig = {
7
+ type: ClearingHouseUserConfigType;
8
+ clearingHouse: ClearingHouse;
9
+ authority: PublicKey;
10
+ };
11
+ declare type WebSocketClearingHouseUserConfig = BaseClearingHouseUserConfig;
12
+ declare type PollingClearingHouseUserConfig = BaseClearingHouseUserConfig & {
13
+ accountLoader: BulkAccountLoader;
14
+ };
15
+ declare type ClearingHouseUserConfig = PollingClearingHouseUserConfig | WebSocketClearingHouseUserConfig;
16
+ export declare function getWebSocketClearingHouseUserConfig(clearingHouse: ClearingHouse, authority: PublicKey): WebSocketClearingHouseUserConfig;
17
+ export declare function getPollingClearingHouseUserConfig(clearingHouse: ClearingHouse, authority: PublicKey, accountLoader: BulkAccountLoader): PollingClearingHouseUserConfig;
18
+ export declare function getClearingHouseUser(config: ClearingHouseUserConfig): ClearingHouseUser;
19
+ export {};
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getClearingHouseUser = exports.getPollingClearingHouseUserConfig = exports.getWebSocketClearingHouseUserConfig = void 0;
4
+ const clearingHouseUser_1 = require("../clearingHouseUser");
5
+ const webSocketUserAccountSubscriber_1 = require("../accounts/webSocketUserAccountSubscriber");
6
+ const pollingUserAccountSubscriber_1 = require("../accounts/pollingUserAccountSubscriber");
7
+ function getWebSocketClearingHouseUserConfig(clearingHouse, authority) {
8
+ return {
9
+ type: 'websocket',
10
+ clearingHouse,
11
+ authority,
12
+ };
13
+ }
14
+ exports.getWebSocketClearingHouseUserConfig = getWebSocketClearingHouseUserConfig;
15
+ function getPollingClearingHouseUserConfig(clearingHouse, authority, accountLoader) {
16
+ return {
17
+ type: 'polling',
18
+ clearingHouse,
19
+ authority,
20
+ accountLoader,
21
+ };
22
+ }
23
+ exports.getPollingClearingHouseUserConfig = getPollingClearingHouseUserConfig;
24
+ function getClearingHouseUser(config) {
25
+ let accountSubscriber;
26
+ if (config.type === 'websocket') {
27
+ accountSubscriber = new webSocketUserAccountSubscriber_1.WebSocketUserAccountSubscriber(config.clearingHouse.program, config.authority);
28
+ }
29
+ else if (config.type === 'polling') {
30
+ accountSubscriber = new pollingUserAccountSubscriber_1.PollingUserAccountSubscriber(config.clearingHouse.program, config.authority, config.accountLoader);
31
+ }
32
+ return new clearingHouseUser_1.ClearingHouseUser(config.clearingHouse, config.authority, accountSubscriber);
33
+ }
34
+ exports.getClearingHouseUser = getClearingHouseUser;