@drift-labs/sdk 0.2.0-master.4 → 0.2.0-master.40

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 (234) hide show
  1. package/README.md +27 -27
  2. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  3. package/lib/accounts/bulkAccountLoader.js +36 -29
  4. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  6. package/lib/accounts/bulkUserSubscription.d.ts +2 -2
  7. package/lib/accounts/bulkUserSubscription.js +0 -1
  8. package/lib/accounts/fetch.d.ts +2 -1
  9. package/lib/accounts/fetch.js +9 -1
  10. package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
  11. package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
  12. package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
  13. package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
  14. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  15. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  16. package/lib/accounts/types.d.ts +26 -15
  17. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  18. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  19. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  20. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  21. package/lib/addresses/marketAddresses.d.ts +1 -3
  22. package/lib/addresses/marketAddresses.js +1 -1
  23. package/lib/addresses/pda.d.ts +15 -9
  24. package/lib/addresses/pda.js +73 -35
  25. package/lib/adminClient.d.ts +65 -0
  26. package/lib/adminClient.js +637 -0
  27. package/lib/config.d.ts +9 -9
  28. package/lib/config.js +25 -21
  29. package/lib/constants/numericConstants.d.ts +30 -12
  30. package/lib/constants/numericConstants.js +41 -21
  31. package/lib/constants/perpMarkets.d.ts +18 -0
  32. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  33. package/lib/constants/spotMarkets.d.ts +19 -0
  34. package/lib/constants/spotMarkets.js +53 -0
  35. package/lib/dlob/DLOB.d.ts +82 -0
  36. package/lib/dlob/DLOB.js +696 -0
  37. package/lib/dlob/DLOBNode.d.ts +54 -0
  38. package/lib/dlob/DLOBNode.js +77 -0
  39. package/lib/dlob/NodeList.d.ts +27 -0
  40. package/lib/dlob/NodeList.js +144 -0
  41. package/lib/driftClient.d.ts +233 -0
  42. package/lib/driftClient.js +2096 -0
  43. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  44. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  45. package/lib/events/eventList.js +3 -0
  46. package/lib/events/eventSubscriber.d.ts +5 -2
  47. package/lib/events/eventSubscriber.js +25 -11
  48. package/lib/events/fetchLogs.d.ts +13 -2
  49. package/lib/events/fetchLogs.js +40 -12
  50. package/lib/events/pollingLogProvider.d.ts +2 -1
  51. package/lib/events/pollingLogProvider.js +7 -3
  52. package/lib/events/sort.js +8 -11
  53. package/lib/events/types.d.ts +9 -3
  54. package/lib/events/types.js +6 -0
  55. package/lib/events/webSocketLogProvider.js +1 -1
  56. package/lib/examples/makeTradeExample.js +30 -18
  57. package/lib/factory/bigNum.d.ts +8 -4
  58. package/lib/factory/bigNum.js +109 -19
  59. package/lib/idl/drift.json +8250 -0
  60. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  61. package/lib/index.d.ts +30 -13
  62. package/lib/index.js +30 -13
  63. package/lib/math/amm.d.ts +9 -6
  64. package/lib/math/amm.js +91 -38
  65. package/lib/math/conversion.js +1 -1
  66. package/lib/math/exchangeStatus.d.ts +4 -0
  67. package/lib/math/exchangeStatus.js +18 -0
  68. package/lib/math/funding.d.ts +6 -6
  69. package/lib/math/funding.js +23 -21
  70. package/lib/math/insurance.d.ts +4 -0
  71. package/lib/math/insurance.js +27 -0
  72. package/lib/math/margin.d.ts +11 -0
  73. package/lib/math/margin.js +82 -0
  74. package/lib/math/market.d.ts +14 -9
  75. package/lib/math/market.js +70 -10
  76. package/lib/math/oracles.d.ts +4 -0
  77. package/lib/math/oracles.js +36 -8
  78. package/lib/math/orders.d.ts +14 -6
  79. package/lib/math/orders.js +90 -17
  80. package/lib/math/position.d.ts +27 -13
  81. package/lib/math/position.js +92 -36
  82. package/lib/math/repeg.js +17 -8
  83. package/lib/math/spotBalance.d.ts +22 -0
  84. package/lib/math/spotBalance.js +192 -0
  85. package/lib/math/spotMarket.d.ts +4 -0
  86. package/lib/math/spotMarket.js +8 -0
  87. package/lib/math/spotPosition.d.ts +6 -0
  88. package/lib/math/spotPosition.js +23 -0
  89. package/lib/math/trade.d.ts +10 -10
  90. package/lib/math/trade.js +27 -31
  91. package/lib/oracles/pythClient.js +1 -1
  92. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  93. package/lib/oracles/switchboardClient.js +1 -1
  94. package/lib/orderParams.d.ts +4 -4
  95. package/lib/orderParams.js +12 -4
  96. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  97. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  98. package/lib/serum/serumSubscriber.d.ts +27 -0
  99. package/lib/serum/serumSubscriber.js +56 -0
  100. package/lib/serum/types.d.ts +11 -0
  101. package/lib/{clearingHouseUserConfig.js → serum/types.js} +0 -0
  102. package/lib/slot/SlotSubscriber.d.ts +7 -0
  103. package/lib/slot/SlotSubscriber.js +3 -0
  104. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  105. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  106. package/lib/tx/retryTxSender.d.ts +1 -1
  107. package/lib/tx/retryTxSender.js +13 -4
  108. package/lib/tx/types.d.ts +1 -1
  109. package/lib/tx/utils.js +1 -1
  110. package/lib/types.d.ts +589 -196
  111. package/lib/types.js +108 -17
  112. package/lib/user.d.ts +226 -0
  113. package/lib/user.js +949 -0
  114. package/lib/userConfig.d.ts +14 -0
  115. package/lib/userConfig.js +2 -0
  116. package/lib/userMap/userMap.d.ts +41 -0
  117. package/lib/userMap/userMap.js +85 -0
  118. package/lib/userMap/userStatsMap.d.ts +19 -0
  119. package/lib/userMap/userStatsMap.js +68 -0
  120. package/lib/userName.d.ts +1 -0
  121. package/lib/userName.js +3 -2
  122. package/lib/userStats.d.ts +18 -0
  123. package/lib/userStats.js +49 -0
  124. package/lib/userStatsConfig.d.ts +14 -0
  125. package/lib/userStatsConfig.js +2 -0
  126. package/lib/util/computeUnits.js +1 -1
  127. package/lib/util/getTokenAddress.d.ts +2 -0
  128. package/lib/util/getTokenAddress.js +9 -0
  129. package/package.json +10 -3
  130. package/src/accounts/bulkAccountLoader.ts +44 -34
  131. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  132. package/src/accounts/bulkUserSubscription.ts +2 -3
  133. package/src/accounts/fetch.ts +27 -2
  134. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  135. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  136. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  137. package/src/accounts/types.ts +35 -15
  138. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  139. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  140. package/src/addresses/marketAddresses.ts +3 -4
  141. package/src/addresses/pda.ts +105 -33
  142. package/src/adminClient.ts +1207 -0
  143. package/src/config.ts +37 -31
  144. package/src/constants/numericConstants.ts +58 -24
  145. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  146. package/src/constants/spotMarkets.ts +73 -0
  147. package/src/dlob/DLOB.ts +1123 -0
  148. package/src/dlob/DLOBNode.ts +155 -0
  149. package/src/dlob/NodeList.ts +195 -0
  150. package/src/driftClient.ts +3564 -0
  151. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  152. package/src/events/eventList.ts +3 -0
  153. package/src/events/eventSubscriber.ts +36 -14
  154. package/src/events/fetchLogs.ts +55 -13
  155. package/src/events/pollingLogProvider.ts +11 -3
  156. package/src/events/sort.ts +11 -15
  157. package/src/events/types.ts +21 -2
  158. package/src/events/webSocketLogProvider.ts +1 -1
  159. package/src/examples/makeTradeExample.ts +44 -28
  160. package/src/factory/bigNum.ts +150 -22
  161. package/src/idl/drift.json +8250 -0
  162. package/src/idl/pyth.json +98 -2
  163. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  164. package/src/index.ts +30 -13
  165. package/src/math/amm.ts +161 -48
  166. package/src/math/conversion.ts +2 -2
  167. package/src/math/exchangeStatus.ts +31 -0
  168. package/src/math/funding.ts +41 -31
  169. package/src/math/insurance.ts +35 -0
  170. package/src/math/margin.ts +133 -0
  171. package/src/math/market.ts +143 -14
  172. package/src/math/oracles.ts +63 -9
  173. package/src/math/orders.ts +163 -26
  174. package/src/math/position.ts +136 -58
  175. package/src/math/repeg.ts +19 -9
  176. package/src/math/spotBalance.ts +319 -0
  177. package/src/math/spotMarket.ts +9 -0
  178. package/src/math/spotPosition.ts +47 -0
  179. package/src/math/trade.ts +33 -37
  180. package/src/oracles/pythClient.ts +2 -2
  181. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  182. package/src/oracles/switchboardClient.ts +2 -2
  183. package/src/orderParams.ts +16 -8
  184. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  185. package/src/serum/serumSubscriber.ts +99 -0
  186. package/src/serum/types.ts +13 -0
  187. package/src/slot/SlotSubscriber.ts +11 -1
  188. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  189. package/src/tx/retryTxSender.ts +16 -5
  190. package/src/tx/types.ts +2 -1
  191. package/src/tx/utils.ts +1 -1
  192. package/src/types.ts +572 -178
  193. package/src/user.ts +1582 -0
  194. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  195. package/src/userMap/userMap.ts +124 -0
  196. package/src/userMap/userStatsMap.ts +108 -0
  197. package/src/userName.ts +2 -1
  198. package/src/userStats.ts +75 -0
  199. package/src/userStatsConfig.ts +18 -0
  200. package/src/util/computeUnits.ts +1 -1
  201. package/src/util/getTokenAddress.ts +18 -0
  202. package/tests/bn/test.ts +46 -11
  203. package/tests/dlob/helpers.ts +611 -0
  204. package/tests/dlob/test.ts +4588 -0
  205. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  206. package/lib/admin.d.ts +0 -44
  207. package/lib/admin.js +0 -433
  208. package/lib/clearingHouse.d.ts +0 -133
  209. package/lib/clearingHouse.js +0 -931
  210. package/lib/clearingHouseUser.d.ts +0 -187
  211. package/lib/clearingHouseUser.js +0 -643
  212. package/lib/clearingHouseUserConfig.d.ts +0 -14
  213. package/lib/constants/banks.d.ts +0 -16
  214. package/lib/constants/banks.js +0 -34
  215. package/lib/constants/markets.d.ts +0 -19
  216. package/lib/idl/clearing_house.json +0 -3998
  217. package/lib/math/bankBalance.d.ts +0 -9
  218. package/lib/math/bankBalance.js +0 -75
  219. package/lib/math/state.d.ts +0 -8
  220. package/lib/math/state.js +0 -15
  221. package/lib/orders.d.ts +0 -8
  222. package/lib/orders.js +0 -134
  223. package/src/admin.ts +0 -722
  224. package/src/clearingHouse.ts +0 -1451
  225. package/src/clearingHouseUser.ts +0 -989
  226. package/src/constants/banks.ts +0 -43
  227. package/src/idl/clearing_house.json +0 -3998
  228. package/src/math/bankBalance.ts +0 -112
  229. package/src/math/state.ts +0 -14
  230. package/src/math/utils.js +0 -27
  231. package/src/math/utils.js.map +0 -1
  232. package/src/orders.ts +0 -244
  233. package/src/util/computeUnits.js +0 -17
  234. package/src/util/computeUnits.js.map +0 -1
@@ -1,26 +1,27 @@
1
1
  import { ConfirmOptions, Connection, PublicKey } from '@solana/web3.js';
2
2
  import { IWallet } from './types';
3
- import { BN } from '@project-serum/anchor';
4
3
  import { OracleInfo } from './oracles/types';
5
4
  import { BulkAccountLoader } from './accounts/bulkAccountLoader';
6
5
  import { DriftEnv } from './config';
7
6
 
8
- export type ClearingHouseConfig = {
7
+ export type DriftClientConfig = {
9
8
  connection: Connection;
10
9
  wallet: IWallet;
11
10
  programID: PublicKey;
12
- accountSubscription?: ClearingHouseSubscriptionConfig;
11
+ accountSubscription?: DriftClientSubscriptionConfig;
13
12
  opts?: ConfirmOptions;
14
13
  txSenderConfig?: TxSenderConfig;
15
- userIds?: number[];
16
- activeUserId?: number;
17
- marketIndexes?: BN[];
18
- bankIndexes?: BN[];
14
+ subAccountIds?: number[];
15
+ activeSubAccountId?: number;
16
+ perpMarketIndexes?: number[];
17
+ spotMarketIndexes?: number[];
19
18
  oracleInfos?: OracleInfo[];
20
19
  env?: DriftEnv;
20
+ userStats?: boolean;
21
+ authority?: PublicKey; // explicitly pass an authority if signer is delegate
21
22
  };
22
23
 
23
- type ClearingHouseSubscriptionConfig =
24
+ type DriftClientSubscriptionConfig =
24
25
  | {
25
26
  type: 'websocket';
26
27
  }
@@ -53,7 +53,10 @@ export class EventList<Type extends EventType> {
53
53
  newNode.next = currentNode.next;
54
54
  if (currentNode.next !== undefined) {
55
55
  newNode.next.prev = newNode;
56
+ } else {
57
+ this.tail = newNode;
56
58
  }
59
+
57
60
  currentNode.next = newNode;
58
61
  newNode.prev = currentNode;
59
62
  }
@@ -25,6 +25,9 @@ export class EventSubscriber {
25
25
  private awaitTxResolver = new Map<string, () => void>();
26
26
  private logProvider: LogProvider;
27
27
  public eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
28
+ private lastSeenSlot: number;
29
+ private lastSeenBlockTime: number | undefined;
30
+ public lastSeenTxSig: string;
28
31
 
29
32
  public constructor(
30
33
  private connection: Connection,
@@ -62,25 +65,29 @@ export class EventSubscriber {
62
65
  }
63
66
  }
64
67
 
65
- public subscribe(): boolean {
66
- if (this.logProvider.isSubscribed()) {
67
- return true;
68
- }
68
+ public async subscribe(): Promise<boolean> {
69
+ try {
70
+ if (this.logProvider.isSubscribed()) {
71
+ return true;
72
+ }
69
73
 
70
- this.fetchPreviousTx().catch((e) => {
74
+ this.logProvider.subscribe((txSig, slot, logs, mostRecentBlockTime) => {
75
+ this.handleTxLogs(txSig, slot, logs, mostRecentBlockTime);
76
+ }, true);
77
+
78
+ return true;
79
+ } catch (e) {
71
80
  console.error('Error fetching previous txs in event subscriber');
72
81
  console.error(e);
73
- });
74
-
75
- return this.logProvider.subscribe((txSig, slot, logs) => {
76
- this.handleTxLogs(txSig, slot, logs);
77
- });
82
+ return false;
83
+ }
78
84
  }
79
85
 
80
86
  private handleTxLogs(
81
87
  txSig: TransactionSignature,
82
88
  slot: number,
83
- logs: string[]
89
+ logs: string[],
90
+ mostRecentBlockTime: number | undefined
84
91
  ): void {
85
92
  if (this.txEventCache.has(txSig)) {
86
93
  return;
@@ -89,6 +96,10 @@ export class EventSubscriber {
89
96
  const wrappedEvents = this.parseEventsFromLogs(txSig, slot, logs);
90
97
  for (const wrappedEvent of wrappedEvents) {
91
98
  this.eventListMap.get(wrappedEvent.eventType).insert(wrappedEvent);
99
+ }
100
+
101
+ // dont emit event till we've added all the events to the eventListMap
102
+ for (const wrappedEvent of wrappedEvents) {
92
103
  this.eventEmitter.emit('newEvent', wrappedEvent);
93
104
  }
94
105
 
@@ -98,11 +109,22 @@ export class EventSubscriber {
98
109
  this.awaitTxResolver.delete(txSig);
99
110
  }
100
111
 
112
+ if (slot > this.lastSeenSlot) {
113
+ this.lastSeenTxSig = txSig;
114
+ }
115
+
116
+ if (
117
+ this.lastSeenBlockTime === undefined ||
118
+ mostRecentBlockTime > this.lastSeenBlockTime
119
+ ) {
120
+ this.lastSeenBlockTime = mostRecentBlockTime;
121
+ }
122
+
101
123
  this.txEventCache.add(txSig, wrappedEvents);
102
124
  }
103
125
 
104
- private async fetchPreviousTx(): Promise<void> {
105
- if (!this.options.untilTx) {
126
+ public async fetchPreviousTx(fetchMax?: boolean): Promise<void> {
127
+ if (!this.options.untilTx && !fetchMax) {
106
128
  return;
107
129
  }
108
130
 
@@ -126,7 +148,7 @@ export class EventSubscriber {
126
148
  beforeTx = response.earliestTx;
127
149
 
128
150
  for (const { txSig, slot, logs } of response.transactionLogs) {
129
- this.handleTxLogs(txSig, slot, logs);
151
+ this.handleTxLogs(txSig, slot, logs, response.mostRecentBlockTime);
130
152
  }
131
153
  }
132
154
  }
@@ -1,35 +1,51 @@
1
+ import { Program } from '@project-serum/anchor';
1
2
  import {
2
3
  Connection,
3
4
  Finality,
4
5
  PublicKey,
6
+ TransactionResponse,
5
7
  TransactionSignature,
6
8
  } from '@solana/web3.js';
9
+ import { WrappedEvents } from './types';
7
10
 
8
11
  type Log = { txSig: TransactionSignature; slot: number; logs: string[] };
9
12
  type FetchLogsResponse = {
10
13
  earliestTx: string;
11
14
  mostRecentTx: string;
15
+ earliestSlot: number;
16
+ mostRecentSlot: number;
12
17
  transactionLogs: Log[];
18
+ mostRecentBlockTime: number | undefined;
13
19
  };
14
20
 
21
+ function mapTransactionResponseToLog(transaction: TransactionResponse): Log {
22
+ return {
23
+ txSig: transaction.transaction.signatures[0],
24
+ slot: transaction.slot,
25
+ logs: transaction.meta.logMessages,
26
+ };
27
+ }
28
+
15
29
  export async function fetchLogs(
16
30
  connection: Connection,
17
31
  programId: PublicKey,
18
32
  finality: Finality,
19
33
  beforeTx?: TransactionSignature,
20
- untilTx?: TransactionSignature
21
- ): Promise<FetchLogsResponse | undefined> {
34
+ untilTx?: TransactionSignature,
35
+ limit?: number
36
+ ): Promise<FetchLogsResponse> {
22
37
  const signatures = await connection.getSignaturesForAddress(
23
38
  programId,
24
39
  {
25
40
  before: beforeTx,
26
41
  until: untilTx,
42
+ limit,
27
43
  },
28
44
  finality
29
45
  );
30
46
 
31
47
  const sortedSignatures = signatures.sort((a, b) =>
32
- a.slot < b.slot ? -1 : 1
48
+ a.slot === b.slot ? 0 : a.slot < b.slot ? -1 : 1
33
49
  );
34
50
 
35
51
  const filteredSignatures = sortedSignatures.filter(
@@ -51,24 +67,22 @@ export async function fetchLogs(
51
67
  );
52
68
 
53
69
  return transactions.map((transaction) => {
54
- return {
55
- txSig: transaction.transaction.signatures[0],
56
- slot: transaction.slot,
57
- logs: transaction.meta.logMessages,
58
- };
70
+ return mapTransactionResponseToLog(transaction);
59
71
  });
60
72
  })
61
73
  )
62
74
  ).flat();
63
75
 
64
- const earliestTx = filteredSignatures[0].signature;
65
- const mostRecentTx =
66
- filteredSignatures[filteredSignatures.length - 1].signature;
76
+ const earliest = filteredSignatures[0];
77
+ const mostRecent = filteredSignatures[filteredSignatures.length - 1];
67
78
 
68
79
  return {
69
80
  transactionLogs: transactionLogs,
70
- earliestTx: earliestTx,
71
- mostRecentTx: mostRecentTx,
81
+ earliestTx: earliest.signature,
82
+ mostRecentTx: mostRecent.signature,
83
+ earliestSlot: earliest.slot,
84
+ mostRecentSlot: mostRecent.slot,
85
+ mostRecentBlockTime: mostRecent.blockTime,
72
86
  };
73
87
  }
74
88
 
@@ -78,3 +92,31 @@ function chunk<T>(array: readonly T[], size: number): T[][] {
78
92
  .map((_, index) => index * size)
79
93
  .map((begin) => array.slice(begin, begin + size));
80
94
  }
95
+
96
+ export class LogParser {
97
+ private program: Program;
98
+
99
+ constructor(program: Program) {
100
+ this.program = program;
101
+ }
102
+
103
+ public parseEventsFromTransaction(
104
+ transaction: TransactionResponse
105
+ ): WrappedEvents {
106
+ const transactionLogObject = mapTransactionResponseToLog(transaction);
107
+
108
+ return this.parseEventsFromLogs(transactionLogObject);
109
+ }
110
+
111
+ public parseEventsFromLogs(event: Log): WrappedEvents {
112
+ const records: WrappedEvents = [];
113
+ // @ts-ignore
114
+ this.program._events._eventParser.parseLogs(event.logs, (eventLog) => {
115
+ eventLog.data.txSig = event.txSig;
116
+ eventLog.data.slot = event.slot;
117
+ eventLog.data.eventType = eventLog.name;
118
+ records.push(eventLog.data);
119
+ });
120
+ return records;
121
+ }
122
+ }
@@ -13,6 +13,7 @@ export class PollingLogProvider implements LogProvider {
13
13
  private intervalId: NodeJS.Timer;
14
14
  private mostRecentSeenTx?: TransactionSignature;
15
15
  private mutex: number;
16
+ private firstFetch = true;
16
17
 
17
18
  public constructor(
18
19
  private connection: Connection,
@@ -23,7 +24,10 @@ export class PollingLogProvider implements LogProvider {
23
24
  this.finality = commitment === 'finalized' ? 'finalized' : 'confirmed';
24
25
  }
25
26
 
26
- public subscribe(callback: logProviderCallback): boolean {
27
+ public subscribe(
28
+ callback: logProviderCallback,
29
+ skipHistory?: boolean
30
+ ): boolean {
27
31
  if (this.intervalId) {
28
32
  return true;
29
33
  }
@@ -40,9 +44,13 @@ export class PollingLogProvider implements LogProvider {
40
44
  this.programId,
41
45
  this.finality,
42
46
  undefined,
43
- this.mostRecentSeenTx
47
+ this.mostRecentSeenTx,
48
+ // If skipping history, only fetch one log back, not the maximum amount available
49
+ skipHistory && this.firstFetch ? 1 : undefined
44
50
  );
45
51
 
52
+ this.firstFetch = false;
53
+
46
54
  if (response === undefined) {
47
55
  return;
48
56
  }
@@ -50,7 +58,7 @@ export class PollingLogProvider implements LogProvider {
50
58
  const { mostRecentTx, transactionLogs } = response;
51
59
 
52
60
  for (const { txSig, slot, logs } of transactionLogs) {
53
- callback(txSig, slot, logs);
61
+ callback(txSig, slot, logs, response.mostRecentBlockTime);
54
62
  }
55
63
 
56
64
  this.mostRecentSeenTx = mostRecentTx;
@@ -6,8 +6,8 @@ import {
6
6
  SortFn,
7
7
  Event,
8
8
  } from './types';
9
- import { OrderRecord } from '../types';
10
- import { PublicKey, ZERO } from '../index';
9
+ import { OrderActionRecord } from '../types';
10
+ import { ZERO } from '../index';
11
11
 
12
12
  function clientSortAscFn(): 'less than' {
13
13
  return 'less than';
@@ -24,21 +24,17 @@ function defaultBlockchainSortFn(
24
24
  return currentEvent.slot <= newEvent.slot ? 'less than' : 'greater than';
25
25
  }
26
26
 
27
- function orderRecordSortFn(
28
- currentEvent: Event<OrderRecord>,
29
- newEvent: Event<OrderRecord>
27
+ function orderActionRecordSortFn(
28
+ currentEvent: Event<OrderActionRecord>,
29
+ newEvent: Event<OrderActionRecord>
30
30
  ): 'less than' | 'greater than' {
31
- const currentEventMarketIndex = !currentEvent.maker.equals(PublicKey.default)
32
- ? currentEvent.makerOrder.marketIndex
33
- : currentEvent.takerOrder.marketIndex;
34
- const newEventMarketIndex = !newEvent.maker.equals(PublicKey.default)
35
- ? newEvent.makerOrder.marketIndex
36
- : newEvent.takerOrder.marketIndex;
37
- if (!currentEventMarketIndex.eq(newEventMarketIndex)) {
31
+ const currentEventMarketIndex = currentEvent.marketIndex;
32
+ const newEventMarketIndex = newEvent.marketIndex;
33
+ if (currentEventMarketIndex !== newEventMarketIndex) {
38
34
  return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
39
35
  }
40
36
 
41
- if (currentEvent.fillRecordId.gt(ZERO) && newEvent.fillRecordId.gt(ZERO)) {
37
+ if (currentEvent.fillRecordId?.gt(ZERO) && newEvent.fillRecordId?.gt(ZERO)) {
42
38
  return currentEvent.fillRecordId.lte(newEvent.fillRecordId)
43
39
  ? 'less than'
44
40
  : 'greater than';
@@ -57,8 +53,8 @@ export function getSortFn(
57
53
  }
58
54
 
59
55
  switch (eventType) {
60
- case 'OrderRecord':
61
- return orderRecordSortFn;
56
+ case 'OrderActionRecord':
57
+ return orderActionRecordSortFn;
62
58
  default:
63
59
  return defaultBlockchainSortFn;
64
60
  }
@@ -4,7 +4,13 @@ import {
4
4
  FundingPaymentRecord,
5
5
  FundingRateRecord,
6
6
  LiquidationRecord,
7
+ NewUserRecord,
8
+ OrderActionRecord,
7
9
  OrderRecord,
10
+ SettlePnlRecord,
11
+ LPRecord,
12
+ InsuranceFundRecord,
13
+ SpotInterestRecord,
8
14
  } from '../index';
9
15
 
10
16
  export type EventSubscriptionOptions = {
@@ -26,7 +32,13 @@ export const DefaultEventSubscriptionOptions: EventSubscriptionOptions = {
26
32
  'FundingPaymentRecord',
27
33
  'LiquidationRecord',
28
34
  'OrderRecord',
35
+ 'OrderActionRecord',
29
36
  'FundingRateRecord',
37
+ 'NewUserRecord',
38
+ 'SettlePnlRecord',
39
+ 'LPRecord',
40
+ 'InsuranceFundRecord',
41
+ 'SpotInterestRecord',
30
42
  ],
31
43
  maxEventsPerType: 4096,
32
44
  orderBy: 'blockchain',
@@ -59,6 +71,12 @@ export type EventMap = {
59
71
  LiquidationRecord: Event<LiquidationRecord>;
60
72
  FundingRateRecord: Event<FundingRateRecord>;
61
73
  OrderRecord: Event<OrderRecord>;
74
+ OrderActionRecord: Event<OrderActionRecord>;
75
+ SettlePnlRecord: Event<SettlePnlRecord>;
76
+ NewUserRecord: Event<NewUserRecord>;
77
+ LPRecord: Event<LPRecord>;
78
+ InsuranceFundRecord: Event<InsuranceFundRecord>;
79
+ SpotInterestRecord: Event<SpotInterestRecord>;
62
80
  };
63
81
 
64
82
  export type EventType = keyof EventMap;
@@ -75,12 +93,13 @@ export type SortFn = (
75
93
  export type logProviderCallback = (
76
94
  txSig: TransactionSignature,
77
95
  slot: number,
78
- logs: string[]
96
+ logs: string[],
97
+ mostRecentBlockTime: number | undefined
79
98
  ) => void;
80
99
 
81
100
  export interface LogProvider {
82
101
  isSubscribed(): boolean;
83
- subscribe(callback: logProviderCallback): boolean;
102
+ subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
84
103
  unsubscribe(): Promise<boolean>;
85
104
  }
86
105
 
@@ -17,7 +17,7 @@ export class WebSocketLogProvider implements LogProvider {
17
17
  this.subscriptionId = this.connection.onLogs(
18
18
  this.programId,
19
19
  (logs, ctx) => {
20
- callback(logs.signature, ctx.slot, logs.logs);
20
+ callback(logs.signature, ctx.slot, logs.logs, undefined);
21
21
  },
22
22
  this.commitment
23
23
  );
@@ -3,17 +3,19 @@ import { Wallet } from '..';
3
3
  import { Token, TOKEN_PROGRAM_ID } from '@solana/spl-token';
4
4
  import { Connection, Keypair, PublicKey } from '@solana/web3.js';
5
5
  import {
6
- calculateMarkPrice,
7
- ClearingHouse,
8
- ClearingHouseUser,
6
+ calculateReservePrice,
7
+ DriftClient,
8
+ User,
9
9
  initialize,
10
10
  PositionDirection,
11
11
  convertToNumber,
12
12
  calculateTradeSlippage,
13
- MARK_PRICE_PRECISION,
13
+ BulkAccountLoader,
14
+ PerpMarkets,
15
+ PRICE_PRECISION,
14
16
  QUOTE_PRECISION,
15
17
  } from '..';
16
- import { Banks } from '../constants/banks';
18
+ import { SpotMarkets } from '../constants/spotMarkets';
17
19
 
18
20
  export const getTokenAddress = (
19
21
  mintAddress: string,
@@ -27,9 +29,11 @@ export const getTokenAddress = (
27
29
  );
28
30
  };
29
31
 
32
+ const cluster = 'devnet';
33
+
30
34
  const main = async () => {
31
35
  // Initialize Drift SDK
32
- const sdkConfig = initialize({ env: 'devnet' });
36
+ const sdkConfig = initialize({ env: cluster });
33
37
 
34
38
  // Set up the Wallet and Provider
35
39
  const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
@@ -60,20 +64,35 @@ const main = async () => {
60
64
  );
61
65
 
62
66
  // Set up the Drift Clearing House
63
- const clearingHousePublicKey = new PublicKey(
64
- sdkConfig.CLEARING_HOUSE_PROGRAM_ID
67
+ const driftPublicKey = new PublicKey(sdkConfig.CLEARING_HOUSE_PROGRAM_ID);
68
+ const bulkAccountLoader = new BulkAccountLoader(
69
+ connection,
70
+ 'confirmed',
71
+ 1000
65
72
  );
66
- const clearingHouse = new ClearingHouse({
73
+ const driftClient = new DriftClient({
67
74
  connection,
68
75
  wallet: provider.wallet,
69
- programID: clearingHousePublicKey,
76
+ programID: driftPublicKey,
77
+ perpMarketIndexes: PerpMarkets[cluster].map((market) => market.marketIndex),
78
+ spotMarketIndexes: SpotMarkets[cluster].map(
79
+ (spotMarket) => spotMarket.marketIndex
80
+ ),
81
+ accountSubscription: {
82
+ type: 'polling',
83
+ accountLoader: bulkAccountLoader,
84
+ },
70
85
  });
71
- await clearingHouse.subscribe();
86
+ await driftClient.subscribe();
72
87
 
73
88
  // Set up Clearing House user client
74
- const user = new ClearingHouseUser({
75
- clearingHouse,
76
- userAccountPublicKey: await clearingHouse.getUserAccountPublicKey(),
89
+ const user = new User({
90
+ driftClient: driftClient,
91
+ userAccountPublicKey: await driftClient.getUserAccountPublicKey(),
92
+ accountSubscription: {
93
+ type: 'polling',
94
+ accountLoader: bulkAccountLoader,
95
+ },
77
96
  });
78
97
 
79
98
  //// Check if clearing house account exists for the current wallet
@@ -82,37 +101,34 @@ const main = async () => {
82
101
  if (!userAccountExists) {
83
102
  //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
84
103
  const depositAmount = new BN(10000).mul(QUOTE_PRECISION);
85
- await clearingHouse.initializeUserAccountAndDepositCollateral(
104
+ await driftClient.initializeUserAccountAndDepositCollateral(
86
105
  depositAmount,
87
106
  await getTokenAddress(
88
107
  usdcTokenAddress.toString(),
89
108
  wallet.publicKey.toString()
90
109
  ),
91
- Banks['devnet'][0].bankIndex
110
+ SpotMarkets['devnet'][0].marketIndex
92
111
  );
93
112
  }
94
113
 
95
114
  await user.subscribe();
96
115
 
97
116
  // Get current price
98
- const solMarketInfo = sdkConfig.MARKETS.find(
117
+ const solMarketInfo = sdkConfig.PERP_MARKETS.find(
99
118
  (market) => market.baseAssetSymbol === 'SOL'
100
119
  );
101
120
 
102
- const currentMarketPrice = calculateMarkPrice(
103
- clearingHouse.getMarketAccount(solMarketInfo.marketIndex),
121
+ const currentMarketPrice = calculateReservePrice(
122
+ driftClient.getPerpMarketAccount(solMarketInfo.marketIndex),
104
123
  undefined
105
124
  );
106
125
 
107
- const formattedPrice = convertToNumber(
108
- currentMarketPrice,
109
- MARK_PRICE_PRECISION
110
- );
126
+ const formattedPrice = convertToNumber(currentMarketPrice, PRICE_PRECISION);
111
127
 
112
128
  console.log(`Current Market Price is $${formattedPrice}`);
113
129
 
114
130
  // Estimate the slippage for a $5000 LONG trade
115
- const solMarketAccount = clearingHouse.getMarketAccount(
131
+ const solMarketAccount = driftClient.getPerpMarketAccount(
116
132
  solMarketInfo.marketIndex
117
133
  );
118
134
 
@@ -125,7 +141,7 @@ const main = async () => {
125
141
  'quote',
126
142
  undefined
127
143
  )[0],
128
- MARK_PRICE_PRECISION
144
+ PRICE_PRECISION
129
145
  );
130
146
 
131
147
  console.log(
@@ -133,7 +149,7 @@ const main = async () => {
133
149
  );
134
150
 
135
151
  // Make a $5000 LONG trade
136
- await clearingHouse.openPosition(
152
+ await driftClient.openPosition(
137
153
  PositionDirection.LONG,
138
154
  longAmount,
139
155
  solMarketInfo.marketIndex
@@ -142,14 +158,14 @@ const main = async () => {
142
158
 
143
159
  // Reduce the position by $2000
144
160
  const reduceAmount = new BN(2000).mul(QUOTE_PRECISION);
145
- await clearingHouse.openPosition(
161
+ await driftClient.openPosition(
146
162
  PositionDirection.SHORT,
147
163
  reduceAmount,
148
164
  solMarketInfo.marketIndex
149
165
  );
150
166
 
151
167
  // Close the rest of the position
152
- await clearingHouse.closePosition(solMarketInfo.marketIndex);
168
+ await driftClient.closePosition(solMarketInfo.marketIndex);
153
169
  };
154
170
 
155
171
  main();