@drift-labs/sdk 2.20.0-beta.0 → 2.20.0-beta.1

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 (81) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +2 -1
  2. package/lib/accounts/bulkAccountLoader.js +7 -7
  3. package/lib/accounts/fetch.d.ts +1 -0
  4. package/lib/accounts/fetch.js +8 -4
  5. package/lib/accounts/pollingDriftClientAccountSubscriber.js +7 -7
  6. package/lib/accounts/pollingTokenAccountSubscriber.js +2 -2
  7. package/lib/accounts/pollingUserAccountSubscriber.js +2 -2
  8. package/lib/accounts/pollingUserStatsAccountSubscriber.js +2 -2
  9. package/lib/accounts/types.d.ts +5 -4
  10. package/lib/accounts/webSocketAccountSubscriber.js +1 -1
  11. package/lib/accounts/webSocketDriftClientAccountSubscriber.js +3 -3
  12. package/lib/addresses/marketAddresses.js +1 -1
  13. package/lib/addresses/pda.js +5 -1
  14. package/lib/adminClient.js +61 -57
  15. package/lib/config.d.ts +2 -2
  16. package/lib/constants/perpMarkets.d.ts +1 -1
  17. package/lib/constants/spotMarkets.d.ts +1 -1
  18. package/lib/dlob/DLOB.d.ts +6 -5
  19. package/lib/dlob/DLOB.js +105 -75
  20. package/lib/dlob/DLOBNode.d.ts +2 -2
  21. package/lib/dlob/DLOBNode.js +7 -7
  22. package/lib/dlob/DLOBOrders.d.ts +2 -2
  23. package/lib/dlob/NodeList.d.ts +1 -1
  24. package/lib/dlob/NodeList.js +2 -2
  25. package/lib/driftClient.d.ts +3 -2
  26. package/lib/driftClient.js +114 -95
  27. package/lib/driftClientConfig.d.ts +3 -3
  28. package/lib/events/eventSubscriber.js +2 -2
  29. package/lib/events/fetchLogs.d.ts +2 -2
  30. package/lib/events/pollingLogProvider.js +1 -1
  31. package/lib/events/types.d.ts +14 -14
  32. package/lib/examples/loadDlob.js +2 -2
  33. package/lib/examples/makeTradeExample.js +9 -9
  34. package/lib/factory/bigNum.js +13 -13
  35. package/lib/factory/oracleClient.js +4 -4
  36. package/lib/idl/drift.json +1 -1
  37. package/lib/index.js +5 -1
  38. package/lib/math/amm.d.ts +1 -1
  39. package/lib/math/amm.js +23 -23
  40. package/lib/math/auction.js +6 -6
  41. package/lib/math/exchangeStatus.js +2 -2
  42. package/lib/math/funding.js +2 -2
  43. package/lib/math/margin.js +4 -4
  44. package/lib/math/market.js +15 -15
  45. package/lib/math/oracles.js +1 -1
  46. package/lib/math/orders.js +27 -24
  47. package/lib/math/position.js +5 -5
  48. package/lib/math/repeg.js +1 -1
  49. package/lib/math/spotBalance.js +9 -9
  50. package/lib/math/spotMarket.js +3 -3
  51. package/lib/math/spotPosition.js +3 -3
  52. package/lib/math/trade.d.ts +1 -1
  53. package/lib/math/trade.js +42 -42
  54. package/lib/math/utils.js +1 -1
  55. package/lib/oracles/oracleClientCache.js +1 -1
  56. package/lib/oracles/pythClient.js +1 -1
  57. package/lib/oracles/types.d.ts +2 -2
  58. package/lib/serum/types.d.ts +1 -1
  59. package/lib/slot/SlotSubscriber.d.ts +1 -1
  60. package/lib/tokenFaucet.js +5 -1
  61. package/lib/tx/retryTxSender.d.ts +1 -1
  62. package/lib/tx/retryTxSender.js +1 -1
  63. package/lib/tx/types.d.ts +1 -1
  64. package/lib/types.d.ts +65 -44
  65. package/lib/user.js +63 -63
  66. package/lib/userConfig.d.ts +2 -2
  67. package/lib/userMap/userMap.js +1 -1
  68. package/lib/userMap/userStatsMap.js +3 -3
  69. package/lib/userStats.js +2 -2
  70. package/lib/userStatsConfig.d.ts +2 -2
  71. package/package.json +1 -1
  72. package/src/accounts/bulkAccountLoader.ts +5 -5
  73. package/src/accounts/fetch.ts +8 -0
  74. package/src/dlob/DLOB.ts +55 -8
  75. package/src/driftClient.ts +28 -0
  76. package/src/idl/drift.json +1 -1
  77. package/src/math/orders.ts +5 -1
  78. package/src/types.ts +22 -0
  79. package/src/userMap/userStatsMap.ts +1 -4
  80. package/tests/amm/test.ts +24 -28
  81. package/tests/dlob/test.ts +67 -73
package/src/dlob/DLOB.ts CHANGED
@@ -60,7 +60,7 @@ type OrderBookCallback = () => void;
60
60
 
61
61
  export type NodeToFill = {
62
62
  node: DLOBNode;
63
- makerNode?: DLOBNode;
63
+ makerNodes: DLOBNode[];
64
64
  };
65
65
 
66
66
  export type NodeToTrigger = {
@@ -512,10 +512,53 @@ export class DLOB {
512
512
  ts,
513
513
  marketType
514
514
  );
515
- return restingLimitOrderNodesToFill.concat(
516
- takingOrderNodesToFill,
517
- expiredNodesToFill
518
- );
515
+
516
+ // for spot, multiple makers isn't supported, so don't merge
517
+ if (isVariant(marketType, 'spot')) {
518
+ return restingLimitOrderNodesToFill.concat(
519
+ takingOrderNodesToFill,
520
+ expiredNodesToFill
521
+ );
522
+ }
523
+
524
+ return this.mergeNodesToFill(
525
+ restingLimitOrderNodesToFill,
526
+ takingOrderNodesToFill
527
+ ).concat(expiredNodesToFill);
528
+ }
529
+
530
+ mergeNodesToFill(
531
+ restingLimitOrderNodesToFill: NodeToFill[],
532
+ takingOrderNodesToFill: NodeToFill[]
533
+ ): NodeToFill[] {
534
+ const mergedNodesToFill = new Map<string, NodeToFill>();
535
+
536
+ const mergeNodesToFillHelper = (nodesToFillArray: NodeToFill[]) => {
537
+ nodesToFillArray.forEach((nodeToFill) => {
538
+ const nodeSignature = getOrderSignature(
539
+ nodeToFill.node.order.orderId,
540
+ nodeToFill.node.userAccount
541
+ );
542
+
543
+ if (!mergedNodesToFill.has(nodeSignature)) {
544
+ mergedNodesToFill.set(nodeSignature, {
545
+ node: nodeToFill.node,
546
+ makerNodes: [],
547
+ });
548
+ }
549
+
550
+ if (nodeToFill.makerNodes) {
551
+ mergedNodesToFill
552
+ .get(nodeSignature)
553
+ .makerNodes.push(...nodeToFill.makerNodes);
554
+ }
555
+ });
556
+ };
557
+
558
+ mergeNodesToFillHelper(restingLimitOrderNodesToFill);
559
+ mergeNodesToFillHelper(takingOrderNodesToFill);
560
+
561
+ return Array.from(mergedNodesToFill.values());
519
562
  }
520
563
 
521
564
  public findRestingLimitOrderNodesToFill(
@@ -768,7 +811,7 @@ export class DLOB {
768
811
 
769
812
  nodesToFill.push({
770
813
  node: takerNode,
771
- makerNode: makerNode,
814
+ makerNodes: [makerNode],
772
815
  });
773
816
 
774
817
  const makerOrder = makerNode.order;
@@ -847,7 +890,7 @@ export class DLOB {
847
890
  if (crosses && fallbackAvailable) {
848
891
  nodesToFill.push({
849
892
  node: node,
850
- makerNode: undefined, // filled by fallback
893
+ makerNodes: [], // filled by fallback
851
894
  });
852
895
  }
853
896
 
@@ -890,6 +933,7 @@ export class DLOB {
890
933
  if (isOrderExpired(bid.order, ts)) {
891
934
  nodesToFill.push({
892
935
  node: bid,
936
+ makerNodes: [],
893
937
  });
894
938
  }
895
939
  }
@@ -900,6 +944,7 @@ export class DLOB {
900
944
  if (isOrderExpired(ask.order, ts)) {
901
945
  nodesToFill.push({
902
946
  node: ask,
947
+ makerNodes: [],
903
948
  });
904
949
  }
905
950
  }
@@ -924,6 +969,7 @@ export class DLOB {
924
969
  )) {
925
970
  nodesToFill.push({
926
971
  node: marketBid,
972
+ makerNodes: [],
927
973
  });
928
974
  }
929
975
 
@@ -935,6 +981,7 @@ export class DLOB {
935
981
  )) {
936
982
  nodesToFill.push({
937
983
  node: marketAsk,
984
+ makerNodes: [],
938
985
  });
939
986
  }
940
987
  return nodesToFill;
@@ -1362,7 +1409,7 @@ export class DLOB {
1362
1409
 
1363
1410
  nodesToFill.push({
1364
1411
  node: takerNode,
1365
- makerNode: makerNode,
1412
+ makerNodes: [makerNode],
1366
1413
  });
1367
1414
 
1368
1415
  if (newAskOrder.baseAssetAmount.eq(newAskOrder.baseAssetAmountFilled)) {
@@ -28,6 +28,8 @@ import {
28
28
  OrderTriggerCondition,
29
29
  isOneOfVariant,
30
30
  PostOnlyParams,
31
+ SpotBalanceType,
32
+ PerpMarketExtendedInfo,
31
33
  } from './types';
32
34
  import * as anchor from '@project-serum/anchor';
33
35
  import driftIDL from './idl/drift.json';
@@ -85,6 +87,7 @@ import { configs, getMarketsAndOraclesForSubscription } from './config';
85
87
  import { WRAPPED_SOL_MINT } from './constants/spotMarkets';
86
88
  import { UserStats } from './userStats';
87
89
  import { isSpotPositionAvailable } from './math/spotPosition';
90
+ import { calculateMarketMaxAvailableInsurance } from './math/market';
88
91
 
89
92
  type RemainingAccountParams = {
90
93
  userAccounts: UserAccount[];
@@ -4155,6 +4158,31 @@ export class DriftClient {
4155
4158
  );
4156
4159
  }
4157
4160
 
4161
+ public getPerpMarketExtendedInfo(
4162
+ marketIndex: number
4163
+ ): PerpMarketExtendedInfo {
4164
+ const marketAccount = this.getPerpMarketAccount(marketIndex);
4165
+ const quoteAccount = this.getSpotMarketAccount(QUOTE_SPOT_MARKET_INDEX);
4166
+
4167
+ const extendedInfo: PerpMarketExtendedInfo = {
4168
+ marketIndex,
4169
+ minOrderSize: marketAccount.amm?.minOrderSize,
4170
+ marginMaintenance: marketAccount.marginRatioMaintenance,
4171
+ pnlPoolValue: getTokenAmount(
4172
+ marketAccount.pnlPool?.scaledBalance,
4173
+ quoteAccount,
4174
+ SpotBalanceType.DEPOSIT
4175
+ ),
4176
+ contractTier: marketAccount.contractTier,
4177
+ availableInsurance: calculateMarketMaxAvailableInsurance(
4178
+ marketAccount,
4179
+ quoteAccount
4180
+ ),
4181
+ };
4182
+
4183
+ return extendedInfo;
4184
+ }
4185
+
4158
4186
  sendTransaction(
4159
4187
  tx: Transaction,
4160
4188
  additionalSigners?: Array<Signer>,
@@ -1,5 +1,5 @@
1
1
  {
2
- "version": "2.20.0-beta.0",
2
+ "version": "2.20.0-beta.1",
3
3
  "name": "drift",
4
4
  "instructions": [
5
5
  {
@@ -217,9 +217,13 @@ export function calculateBaseAssetAmountToFillUpToLimitPrice(
217
217
  limitPrice: BN,
218
218
  oraclePriceData: OraclePriceData
219
219
  ): BN {
220
+ const adjustedLimitPrice = isVariant(order.direction, 'long')
221
+ ? limitPrice.sub(amm.orderTickSize)
222
+ : limitPrice.add(amm.orderTickSize);
223
+
220
224
  const [maxAmountToTrade, direction] = calculateMaxBaseAssetAmountToTrade(
221
225
  amm,
222
- limitPrice,
226
+ adjustedLimitPrice,
223
227
  order.direction,
224
228
  oraclePriceData
225
229
  );
package/src/types.ts CHANGED
@@ -998,3 +998,25 @@ export type SerumV3FulfillmentConfigAccount = {
998
998
  serumOpenOrders: PublicKey;
999
999
  serumSignerNonce: BN;
1000
1000
  };
1001
+
1002
+ export type PerpMarketExtendedInfo = {
1003
+ marketIndex: number;
1004
+ /**
1005
+ * Min order size measured in base asset, using base precision
1006
+ */
1007
+ minOrderSize: BN;
1008
+ /**
1009
+ * Margin maintenance percentage, using margin precision (1e4)
1010
+ */
1011
+ marginMaintenance: number;
1012
+ /**
1013
+ * Max insurance available, measured in quote asset, using quote preicision
1014
+ */
1015
+ availableInsurance: BN;
1016
+ /**
1017
+ * Pnl pool available, this is measured in quote asset, using quote precision.
1018
+ * Should be generated by using getTokenAmount and passing in the scaled balance of the base asset + quote spot account
1019
+ */
1020
+ pnlPoolValue: BN;
1021
+ contractTier: ContractTier;
1022
+ };
@@ -52,10 +52,7 @@ export class UserStatsMap {
52
52
 
53
53
  const chUserStat = new UserStats({
54
54
  driftClient: this.driftClient,
55
- userStatsAccountPublicKey: getUserStatsAccountPublicKey(
56
- this.driftClient.program.programId,
57
- userStat.authority
58
- ),
55
+ userStatsAccountPublicKey: programUserAccount.publicKey,
59
56
  accountSubscription: this.accountSubscription,
60
57
  });
61
58
  userStatArray.push(chUserStat);
package/tests/amm/test.ts CHANGED
@@ -45,7 +45,7 @@ describe('AMM Tests', () => {
45
45
  AMM_RESERVE_PRECISION.div(new BN(2)),
46
46
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
47
47
  250,
48
- 30000,
48
+ 30000
49
49
  );
50
50
  assert(iscale == 1);
51
51
 
@@ -55,42 +55,42 @@ describe('AMM Tests', () => {
55
55
  AMM_RESERVE_PRECISION.div(new BN(2)),
56
56
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
57
57
  250,
58
- 30000,
58
+ 30000
59
59
  );
60
60
  assert(iscale == 1);
61
61
 
62
- let baa = new BN(1000);
62
+ let baa = new BN(1000);
63
63
  iscale = calculateInventoryScale(
64
64
  baa,
65
65
  AMM_RESERVE_PRECISION.add(baa),
66
66
  AMM_RESERVE_PRECISION.div(new BN(2)),
67
67
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
68
68
  250,
69
- 30000,
69
+ 30000
70
70
  );
71
71
  console.log(iscale);
72
72
  assert(iscale == 1.00024);
73
73
 
74
- baa = new BN(100000);
74
+ baa = new BN(100000);
75
75
  iscale = calculateInventoryScale(
76
76
  baa,
77
77
  AMM_RESERVE_PRECISION.add(baa),
78
78
  AMM_RESERVE_PRECISION.div(new BN(2)),
79
79
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
80
80
  250,
81
- 30000,
81
+ 30000
82
82
  );
83
83
  console.log(iscale);
84
84
  assert(iscale == 1.024);
85
85
 
86
- baa = new BN(1000000);
86
+ baa = new BN(1000000);
87
87
  iscale = calculateInventoryScale(
88
88
  baa,
89
89
  AMM_RESERVE_PRECISION.add(baa),
90
90
  AMM_RESERVE_PRECISION.div(new BN(2)),
91
91
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
92
92
  250,
93
- 30000,
93
+ 30000
94
94
  );
95
95
  console.log(iscale);
96
96
  assert(iscale == 1.24048);
@@ -102,7 +102,7 @@ describe('AMM Tests', () => {
102
102
  AMM_RESERVE_PRECISION.div(new BN(2)),
103
103
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
104
104
  250,
105
- 30000,
105
+ 30000
106
106
  );
107
107
  console.log(iscale);
108
108
  assert(iscale == 3.44896);
@@ -114,12 +114,11 @@ describe('AMM Tests', () => {
114
114
  AMM_RESERVE_PRECISION.div(new BN(2)),
115
115
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
116
116
  250,
117
- 30000,
117
+ 30000
118
118
  );
119
119
  console.log(iscale);
120
120
  assert(iscale == 14.33332);
121
121
 
122
-
123
122
  baa = AMM_RESERVE_PRECISION.div(new BN(4)); // 50%
124
123
  iscale = calculateInventoryScale(
125
124
  baa,
@@ -127,7 +126,7 @@ describe('AMM Tests', () => {
127
126
  AMM_RESERVE_PRECISION.div(new BN(2)),
128
127
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
129
128
  250,
130
- 30000,
129
+ 30000
131
130
  );
132
131
  console.log(iscale);
133
132
  assert(iscale == 120); //100%
@@ -139,7 +138,7 @@ describe('AMM Tests', () => {
139
138
  AMM_RESERVE_PRECISION.div(new BN(2)),
140
139
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
141
140
  250,
142
- 30000 * 2,
141
+ 30000 * 2
143
142
  );
144
143
  console.log(iscale);
145
144
  assert(iscale == 120 * 2); //100%
@@ -151,21 +150,21 @@ describe('AMM Tests', () => {
151
150
  AMM_RESERVE_PRECISION.div(new BN(2)),
152
151
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
153
152
  250,
154
- 30000 * 2,
153
+ 30000 * 2
155
154
  );
156
- assert(iscale == 160.99984);
155
+ assert(iscale == 160.99984);
157
156
 
158
- baa = new BN(855329058);
157
+ baa = new BN(855329058);
159
158
  iscale = calculateInventoryScale(
160
159
  baa,
161
160
  AMM_RESERVE_PRECISION.add(baa),
162
161
  AMM_RESERVE_PRECISION.div(new BN(2)),
163
162
  AMM_RESERVE_PRECISION,
164
163
  250,
165
- 30000,
164
+ 30000
166
165
  ); // >100%
167
166
  assert(iscale == 120);
168
- assert(250*iscale == 30000);
167
+ assert(250 * iscale == 30000);
169
168
 
170
169
  iscale = calculateInventoryScale(
171
170
  baa,
@@ -173,10 +172,10 @@ describe('AMM Tests', () => {
173
172
  AMM_RESERVE_PRECISION.div(new BN(2)),
174
173
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
175
174
  250,
176
- 30000,
175
+ 30000
177
176
  );
178
177
  assert(iscale == 120);
179
- assert(250*iscale == 30000);
178
+ assert(250 * iscale == 30000);
180
179
 
181
180
  baa = new BN(-855329058); // ~85%
182
181
  iscale = calculateInventoryScale(
@@ -185,10 +184,10 @@ describe('AMM Tests', () => {
185
184
  AMM_RESERVE_PRECISION.div(new BN(2)),
186
185
  AMM_RESERVE_PRECISION.mul(new BN(3)).div(new BN(2)),
187
186
  250,
188
- 30000,
187
+ 30000
189
188
  );
190
189
  assert(iscale == 120);
191
- assert(250*iscale == 30000);
190
+ assert(250 * iscale == 30000);
192
191
 
193
192
  // 'bonk' scale
194
193
  iscale = calculateInventoryScale(
@@ -197,15 +196,12 @@ describe('AMM Tests', () => {
197
196
  new BN('2443167585342470000'),
198
197
  new BN('2545411471321696000'),
199
198
  3500,
200
- 100000,
199
+ 100000
201
200
  );
202
201
  console.log(iscale);
203
- console.log(3500*iscale/1e6);
202
+ console.log((3500 * iscale) / 1e6);
204
203
  assert(iscale == 18.762285);
205
- assert(3500*iscale/1e6 == 0.06566799749999999); //6.5%
206
-
207
-
208
-
204
+ assert((3500 * iscale) / 1e6 == 0.06566799749999999); //6.5%
209
205
  });
210
206
 
211
207
  it('Various Spreads', () => {