@drift-labs/sdk 0.2.0-temp.1 → 2.0.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 (274) hide show
  1. package/README.md +27 -29
  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/pollingUserAccountSubscriber.d.ts +1 -1
  15. package/lib/accounts/pollingUserAccountSubscriber.js +5 -11
  16. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  17. package/lib/accounts/pollingUserStatsAccountSubscriber.js +107 -0
  18. package/lib/accounts/types.d.ts +26 -15
  19. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  20. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  21. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  22. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  23. package/lib/addresses/marketAddresses.d.ts +1 -3
  24. package/lib/addresses/marketAddresses.js +1 -1
  25. package/lib/addresses/pda.d.ts +15 -9
  26. package/lib/addresses/pda.js +73 -35
  27. package/lib/adminClient.d.ts +65 -0
  28. package/lib/adminClient.js +637 -0
  29. package/lib/config.d.ts +10 -10
  30. package/lib/config.js +26 -22
  31. package/lib/constants/numericConstants.d.ts +29 -12
  32. package/lib/constants/numericConstants.js +40 -21
  33. package/lib/constants/perpMarkets.d.ts +18 -0
  34. package/lib/constants/{markets.js → perpMarkets.js} +20 -9
  35. package/lib/constants/spotMarkets.d.ts +19 -0
  36. package/lib/constants/spotMarkets.js +63 -0
  37. package/lib/dlob/DLOB.d.ts +82 -0
  38. package/lib/dlob/DLOB.js +694 -0
  39. package/lib/dlob/DLOBNode.d.ts +54 -0
  40. package/lib/dlob/DLOBNode.js +77 -0
  41. package/lib/dlob/NodeList.d.ts +27 -0
  42. package/lib/dlob/NodeList.js +144 -0
  43. package/lib/driftClient.d.ts +234 -0
  44. package/lib/driftClient.js +2108 -0
  45. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  46. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  47. package/lib/events/eventList.js +3 -0
  48. package/lib/events/eventSubscriber.d.ts +5 -2
  49. package/lib/events/eventSubscriber.js +25 -11
  50. package/lib/events/fetchLogs.d.ts +13 -2
  51. package/lib/events/fetchLogs.js +45 -14
  52. package/lib/events/pollingLogProvider.d.ts +2 -1
  53. package/lib/events/pollingLogProvider.js +7 -3
  54. package/lib/events/sort.js +8 -11
  55. package/lib/events/types.d.ts +11 -3
  56. package/lib/events/types.js +8 -0
  57. package/lib/events/webSocketLogProvider.js +1 -1
  58. package/lib/examples/makeTradeExample.js +30 -18
  59. package/lib/factory/bigNum.d.ts +8 -4
  60. package/lib/factory/bigNum.js +109 -19
  61. package/lib/idl/drift.json +8392 -0
  62. package/lib/index.d.ts +29 -12
  63. package/lib/index.js +29 -12
  64. package/lib/math/amm.d.ts +9 -6
  65. package/lib/math/amm.js +91 -38
  66. package/lib/math/conversion.js +1 -1
  67. package/lib/math/exchangeStatus.d.ts +4 -0
  68. package/lib/math/exchangeStatus.js +18 -0
  69. package/lib/math/funding.d.ts +6 -6
  70. package/lib/math/funding.js +23 -21
  71. package/lib/math/insurance.d.ts +4 -0
  72. package/lib/math/insurance.js +27 -0
  73. package/lib/math/margin.d.ts +11 -0
  74. package/lib/math/margin.js +82 -0
  75. package/lib/math/market.d.ts +14 -9
  76. package/lib/math/market.js +70 -10
  77. package/lib/math/oracles.d.ts +4 -0
  78. package/lib/math/oracles.js +36 -8
  79. package/lib/math/orders.d.ts +16 -6
  80. package/lib/math/orders.js +97 -17
  81. package/lib/math/position.d.ts +27 -13
  82. package/lib/math/position.js +91 -37
  83. package/lib/math/repeg.js +17 -8
  84. package/lib/math/spotBalance.d.ts +22 -0
  85. package/lib/math/spotBalance.js +192 -0
  86. package/lib/math/spotMarket.d.ts +4 -0
  87. package/lib/math/spotMarket.js +8 -0
  88. package/lib/math/spotPosition.d.ts +6 -0
  89. package/lib/math/spotPosition.js +23 -0
  90. package/lib/math/trade.d.ts +10 -10
  91. package/lib/math/trade.js +27 -31
  92. package/lib/oracles/pythClient.js +1 -1
  93. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  94. package/lib/oracles/switchboardClient.js +1 -1
  95. package/lib/orderParams.d.ts +4 -4
  96. package/lib/orderParams.js +12 -4
  97. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  98. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  99. package/lib/serum/serumSubscriber.d.ts +27 -0
  100. package/lib/serum/serumSubscriber.js +56 -0
  101. package/lib/serum/types.d.ts +11 -0
  102. package/{src/oracles → lib/serum}/types.js +0 -0
  103. package/lib/tokenFaucet.d.ts +1 -0
  104. package/lib/tokenFaucet.js +23 -12
  105. package/lib/tx/retryTxSender.d.ts +1 -1
  106. package/lib/tx/retryTxSender.js +13 -4
  107. package/lib/tx/types.d.ts +1 -1
  108. package/lib/types.d.ts +631 -222
  109. package/lib/types.js +137 -24
  110. package/lib/user.d.ts +228 -0
  111. package/lib/user.js +959 -0
  112. package/lib/userConfig.d.ts +14 -0
  113. package/lib/{clearingHouseUserConfig.js → userConfig.js} +0 -0
  114. package/lib/userMap/userMap.d.ts +41 -0
  115. package/lib/userMap/userMap.js +85 -0
  116. package/lib/userMap/userStatsMap.d.ts +19 -0
  117. package/lib/userMap/userStatsMap.js +68 -0
  118. package/lib/userName.d.ts +1 -0
  119. package/lib/userName.js +3 -2
  120. package/lib/userStats.d.ts +18 -0
  121. package/lib/userStats.js +49 -0
  122. package/lib/userStatsConfig.d.ts +14 -0
  123. package/{src/clearingHouseConfig.js → lib/userStatsConfig.js} +0 -0
  124. package/lib/util/getTokenAddress.d.ts +2 -0
  125. package/lib/util/getTokenAddress.js +9 -0
  126. package/package.json +12 -5
  127. package/src/accounts/bulkAccountLoader.ts +44 -34
  128. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  129. package/src/accounts/bulkUserSubscription.ts +2 -3
  130. package/src/accounts/fetch.ts +27 -2
  131. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  132. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  133. package/src/accounts/pollingUserAccountSubscriber.ts +5 -12
  134. package/src/accounts/pollingUserStatsAccountSubscriber.ts +166 -0
  135. package/src/accounts/types.ts +35 -15
  136. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  137. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  138. package/src/addresses/marketAddresses.ts +3 -4
  139. package/src/addresses/pda.ts +105 -33
  140. package/src/adminClient.ts +1207 -0
  141. package/src/config.ts +41 -34
  142. package/src/constants/numericConstants.ts +59 -26
  143. package/src/constants/{markets.ts → perpMarkets.ts} +22 -11
  144. package/src/constants/spotMarkets.ts +83 -0
  145. package/src/dlob/DLOB.ts +1120 -0
  146. package/src/dlob/DLOBNode.ts +155 -0
  147. package/src/dlob/NodeList.ts +195 -0
  148. package/src/driftClient.ts +3594 -0
  149. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  150. package/src/events/eventList.ts +3 -0
  151. package/src/events/eventSubscriber.ts +36 -14
  152. package/src/events/fetchLogs.ts +60 -15
  153. package/src/events/pollingLogProvider.ts +11 -3
  154. package/src/events/sort.ts +11 -15
  155. package/src/events/types.ts +27 -2
  156. package/src/events/webSocketLogProvider.ts +1 -1
  157. package/src/examples/makeTradeExample.js +152 -75
  158. package/src/examples/makeTradeExample.ts +44 -28
  159. package/src/factory/bigNum.ts +150 -22
  160. package/src/idl/drift.json +8392 -0
  161. package/src/idl/pyth.json +98 -2
  162. package/src/index.ts +29 -12
  163. package/src/math/amm.ts +161 -48
  164. package/src/math/conversion.ts +2 -2
  165. package/src/math/exchangeStatus.ts +31 -0
  166. package/src/math/funding.ts +41 -31
  167. package/src/math/insurance.ts +35 -0
  168. package/src/math/margin.ts +133 -0
  169. package/src/math/market.ts +143 -14
  170. package/src/math/oracles.ts +63 -9
  171. package/src/math/orders.ts +168 -26
  172. package/src/math/position.ts +133 -59
  173. package/src/math/repeg.ts +19 -9
  174. package/src/math/spotBalance.ts +319 -0
  175. package/src/math/spotMarket.ts +9 -0
  176. package/src/math/spotPosition.ts +47 -0
  177. package/src/math/trade.ts +33 -37
  178. package/src/oracles/pythClient.ts +2 -2
  179. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  180. package/src/oracles/switchboardClient.ts +2 -2
  181. package/src/orderParams.ts +16 -8
  182. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  183. package/src/serum/serumSubscriber.ts +99 -0
  184. package/src/serum/types.ts +13 -0
  185. package/src/tokenFaucet.ts +38 -15
  186. package/src/tx/retryTxSender.ts +16 -5
  187. package/src/tx/types.ts +2 -1
  188. package/src/types.ts +594 -195
  189. package/src/user.ts +1599 -0
  190. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  191. package/src/userMap/userMap.ts +124 -0
  192. package/src/userMap/userStatsMap.ts +108 -0
  193. package/src/userName.ts +2 -1
  194. package/src/userStats.ts +75 -0
  195. package/src/userStatsConfig.ts +18 -0
  196. package/src/util/getTokenAddress.ts +18 -0
  197. package/tests/bn/test.ts +46 -11
  198. package/tests/dlob/helpers.ts +619 -0
  199. package/tests/dlob/test.ts +4586 -0
  200. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  201. package/lib/admin.d.ts +0 -44
  202. package/lib/admin.js +0 -438
  203. package/lib/clearingHouse.d.ts +0 -146
  204. package/lib/clearingHouse.js +0 -1154
  205. package/lib/clearingHouseUser.d.ts +0 -187
  206. package/lib/clearingHouseUser.js +0 -634
  207. package/lib/clearingHouseUserConfig.d.ts +0 -14
  208. package/lib/constants/banks.d.ts +0 -16
  209. package/lib/constants/banks.js +0 -41
  210. package/lib/constants/markets.d.ts +0 -19
  211. package/lib/idl/clearing_house.json +0 -4464
  212. package/lib/math/bankBalance.d.ts +0 -9
  213. package/lib/math/bankBalance.js +0 -75
  214. package/lib/math/state.d.ts +0 -8
  215. package/lib/math/state.js +0 -15
  216. package/lib/orders.d.ts +0 -8
  217. package/lib/orders.js +0 -134
  218. package/src/accounts/bulkAccountLoader.js +0 -197
  219. package/src/accounts/bulkUserSubscription.js +0 -33
  220. package/src/accounts/pollingClearingHouseAccountSubscriber.js +0 -311
  221. package/src/accounts/pollingOracleSubscriber.js +0 -93
  222. package/src/accounts/pollingTokenAccountSubscriber.js +0 -90
  223. package/src/accounts/pollingUserAccountSubscriber.js +0 -132
  224. package/src/accounts/types.js +0 -10
  225. package/src/accounts/utils.js +0 -7
  226. package/src/accounts/webSocketAccountSubscriber.js +0 -93
  227. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +0 -233
  228. package/src/accounts/webSocketUserAccountSubscriber.js +0 -62
  229. package/src/addresses/marketAddresses.js +0 -26
  230. package/src/admin.js +0 -517
  231. package/src/admin.ts +0 -730
  232. package/src/clearingHouse.ts +0 -1828
  233. package/src/clearingHouseUser.ts +0 -978
  234. package/src/clearingHouseUserConfig.js +0 -2
  235. package/src/config.js +0 -67
  236. package/src/constants/banks.js +0 -42
  237. package/src/constants/banks.ts +0 -50
  238. package/src/constants/markets.js +0 -42
  239. package/src/constants/numericConstants.js +0 -41
  240. package/src/events/eventSubscriber.js +0 -139
  241. package/src/events/fetchLogs.js +0 -50
  242. package/src/events/pollingLogProvider.js +0 -64
  243. package/src/events/sort.js +0 -44
  244. package/src/events/txEventCache.js +0 -71
  245. package/src/events/types.js +0 -20
  246. package/src/events/webSocketLogProvider.js +0 -41
  247. package/src/factory/bigNum.js +0 -390
  248. package/src/factory/oracleClient.js +0 -20
  249. package/src/idl/clearing_house.json +0 -4464
  250. package/src/index.js +0 -69
  251. package/src/math/amm.js +0 -369
  252. package/src/math/auction.js +0 -42
  253. package/src/math/bankBalance.ts +0 -112
  254. package/src/math/conversion.js +0 -11
  255. package/src/math/funding.js +0 -248
  256. package/src/math/oracles.js +0 -26
  257. package/src/math/repeg.js +0 -128
  258. package/src/math/state.js +0 -15
  259. package/src/math/state.ts +0 -14
  260. package/src/math/trade.js +0 -253
  261. package/src/math/utils.js +0 -26
  262. package/src/math/utils.js.map +0 -1
  263. package/src/mockUSDCFaucet.js +0 -280
  264. package/src/oracles/oracleClientCache.js +0 -19
  265. package/src/oracles/pythClient.js +0 -46
  266. package/src/oracles/quoteAssetOracleClient.js +0 -32
  267. package/src/oracles/switchboardClient.js +0 -69
  268. package/src/orderParams.js +0 -20
  269. package/src/orders.ts +0 -245
  270. package/src/slot/SlotSubscriber.js +0 -39
  271. package/src/tokenFaucet.js +0 -189
  272. package/src/types.js +0 -125
  273. package/src/userName.js +0 -20
  274. package/src/wallet.js +0 -35
@@ -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(
@@ -50,25 +66,26 @@ export async function fetchLogs(
50
66
  finality
51
67
  );
52
68
 
53
- return transactions.map((transaction) => {
54
- return {
55
- txSig: transaction.transaction.signatures[0],
56
- slot: transaction.slot,
57
- logs: transaction.meta.logMessages,
58
- };
59
- });
69
+ return transactions.reduce((logs, transaction) => {
70
+ if (transaction) {
71
+ logs.push(mapTransactionResponseToLog(transaction));
72
+ }
73
+ return logs;
74
+ }, new Array<Log>());
60
75
  })
61
76
  )
62
77
  ).flat();
63
78
 
64
- const earliestTx = filteredSignatures[0].signature;
65
- const mostRecentTx =
66
- filteredSignatures[filteredSignatures.length - 1].signature;
79
+ const earliest = filteredSignatures[0];
80
+ const mostRecent = filteredSignatures[filteredSignatures.length - 1];
67
81
 
68
82
  return {
69
83
  transactionLogs: transactionLogs,
70
- earliestTx: earliestTx,
71
- mostRecentTx: mostRecentTx,
84
+ earliestTx: earliest.signature,
85
+ mostRecentTx: mostRecent.signature,
86
+ earliestSlot: earliest.slot,
87
+ mostRecentSlot: mostRecent.slot,
88
+ mostRecentBlockTime: mostRecent.blockTime,
72
89
  };
73
90
  }
74
91
 
@@ -78,3 +95,31 @@ function chunk<T>(array: readonly T[], size: number): T[][] {
78
95
  .map((_, index) => index * size)
79
96
  .map((begin) => array.slice(begin, begin + size));
80
97
  }
98
+
99
+ export class LogParser {
100
+ private program: Program;
101
+
102
+ constructor(program: Program) {
103
+ this.program = program;
104
+ }
105
+
106
+ public parseEventsFromTransaction(
107
+ transaction: TransactionResponse
108
+ ): WrappedEvents {
109
+ const transactionLogObject = mapTransactionResponseToLog(transaction);
110
+
111
+ return this.parseEventsFromLogs(transactionLogObject);
112
+ }
113
+
114
+ public parseEventsFromLogs(event: Log): WrappedEvents {
115
+ const records: WrappedEvents = [];
116
+ // @ts-ignore
117
+ this.program._events._eventParser.parseLogs(event.logs, (eventLog) => {
118
+ eventLog.data.txSig = event.txSig;
119
+ eventLog.data.slot = event.slot;
120
+ eventLog.data.eventType = eventLog.name;
121
+ records.push(eventLog.data);
122
+ });
123
+ return records;
124
+ }
125
+ }
@@ -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,15 @@ 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,
14
+ InsuranceFundStakeRecord,
15
+ CurveRecord,
8
16
  } from '../index';
9
17
 
10
18
  export type EventSubscriptionOptions = {
@@ -26,7 +34,15 @@ export const DefaultEventSubscriptionOptions: EventSubscriptionOptions = {
26
34
  'FundingPaymentRecord',
27
35
  'LiquidationRecord',
28
36
  'OrderRecord',
37
+ 'OrderActionRecord',
29
38
  'FundingRateRecord',
39
+ 'NewUserRecord',
40
+ 'SettlePnlRecord',
41
+ 'LPRecord',
42
+ 'InsuranceFundRecord',
43
+ 'SpotInterestRecord',
44
+ 'InsuranceFundStakeRecord',
45
+ 'CurveRecord',
30
46
  ],
31
47
  maxEventsPerType: 4096,
32
48
  orderBy: 'blockchain',
@@ -59,6 +75,14 @@ export type EventMap = {
59
75
  LiquidationRecord: Event<LiquidationRecord>;
60
76
  FundingRateRecord: Event<FundingRateRecord>;
61
77
  OrderRecord: Event<OrderRecord>;
78
+ OrderActionRecord: Event<OrderActionRecord>;
79
+ SettlePnlRecord: Event<SettlePnlRecord>;
80
+ NewUserRecord: Event<NewUserRecord>;
81
+ LPRecord: Event<LPRecord>;
82
+ InsuranceFundRecord: Event<InsuranceFundRecord>;
83
+ SpotInterestRecord: Event<SpotInterestRecord>;
84
+ InsuranceFundStakeRecord: Event<InsuranceFundStakeRecord>;
85
+ CurveRecord: Event<CurveRecord>;
62
86
  };
63
87
 
64
88
  export type EventType = keyof EventMap;
@@ -75,12 +99,13 @@ export type SortFn = (
75
99
  export type logProviderCallback = (
76
100
  txSig: TransactionSignature,
77
101
  slot: number,
78
- logs: string[]
102
+ logs: string[],
103
+ mostRecentBlockTime: number | undefined
79
104
  ) => void;
80
105
 
81
106
  export interface LogProvider {
82
107
  isSubscribed(): boolean;
83
- subscribe(callback: logProviderCallback): boolean;
108
+ subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
84
109
  unsubscribe(): Promise<boolean>;
85
110
  }
86
111
 
@@ -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
  );
@@ -1,80 +1,157 @@
1
- "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- Object.defineProperty(exports, "__esModule", { value: true });
1
+ 'use strict';
2
+ var __awaiter =
3
+ (this && this.__awaiter) ||
4
+ function (thisArg, _arguments, P, generator) {
5
+ function adopt(value) {
6
+ return value instanceof P
7
+ ? value
8
+ : new P(function (resolve) {
9
+ resolve(value);
10
+ });
11
+ }
12
+ return new (P || (P = Promise))(function (resolve, reject) {
13
+ function fulfilled(value) {
14
+ try {
15
+ step(generator.next(value));
16
+ } catch (e) {
17
+ reject(e);
18
+ }
19
+ }
20
+ function rejected(value) {
21
+ try {
22
+ step(generator['throw'](value));
23
+ } catch (e) {
24
+ reject(e);
25
+ }
26
+ }
27
+ function step(result) {
28
+ result.done
29
+ ? resolve(result.value)
30
+ : adopt(result.value).then(fulfilled, rejected);
31
+ }
32
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
33
+ });
34
+ };
35
+ Object.defineProperty(exports, '__esModule', { value: true });
12
36
  exports.getTokenAddress = void 0;
13
- const anchor_1 = require("@project-serum/anchor");
14
- const __1 = require("..");
15
- const spl_token_1 = require("@solana/spl-token");
16
- const web3_js_1 = require("@solana/web3.js");
17
- const __2 = require("..");
18
- const banks_1 = require("../constants/banks");
37
+ const anchor_1 = require('@project-serum/anchor');
38
+ const __1 = require('..');
39
+ const spl_token_1 = require('@solana/spl-token');
40
+ const web3_js_1 = require('@solana/web3.js');
41
+ const __2 = require('..');
42
+ const banks_1 = require('../constants/spotMarkets');
19
43
  const getTokenAddress = (mintAddress, userPubKey) => {
20
- return spl_token_1.Token.getAssociatedTokenAddress(new web3_js_1.PublicKey(`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`), spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
44
+ return spl_token_1.Token.getAssociatedTokenAddress(
45
+ new web3_js_1.PublicKey(`ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL`),
46
+ spl_token_1.TOKEN_PROGRAM_ID,
47
+ new web3_js_1.PublicKey(mintAddress),
48
+ new web3_js_1.PublicKey(userPubKey)
49
+ );
21
50
  };
22
51
  exports.getTokenAddress = getTokenAddress;
23
- const main = () => __awaiter(void 0, void 0, void 0, function* () {
24
- // Initialize Drift SDK
25
- const sdkConfig = __2.initialize({ env: 'devnet' });
26
- // Set up the Wallet and Provider
27
- const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
28
- const keypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(privateKey)));
29
- const wallet = new __1.Wallet(keypair);
30
- // Set up the Connection
31
- const rpcAddress = process.env.RPC_ADDRESS; // can use: https://api.devnet.solana.com for devnet; https://api.mainnet-beta.solana.com for mainnet;
32
- const connection = new web3_js_1.Connection(rpcAddress);
33
- // Set up the Provider
34
- const provider = new anchor_1.AnchorProvider(connection, wallet, anchor_1.AnchorProvider.defaultOptions());
35
- // Check SOL Balance
36
- const lamportsBalance = yield connection.getBalance(wallet.publicKey);
37
- console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
38
- // Misc. other things to set up
39
- const usdcTokenAddress = yield exports.getTokenAddress(sdkConfig.USDC_MINT_ADDRESS, wallet.publicKey.toString());
40
- // Set up the Drift Clearing House
41
- const clearingHousePublicKey = new web3_js_1.PublicKey(sdkConfig.CLEARING_HOUSE_PROGRAM_ID);
42
- const clearingHouse = new __2.ClearingHouse({
43
- connection,
44
- wallet: provider.wallet,
45
- programID: clearingHousePublicKey,
46
- });
47
- yield clearingHouse.subscribe();
48
- // Set up Clearing House user client
49
- const user = new __2.ClearingHouseUser({
50
- clearingHouse,
51
- userAccountPublicKey: yield clearingHouse.getUserAccountPublicKey(),
52
- });
53
- //// Check if clearing house account exists for the current wallet
54
- const userAccountExists = yield user.exists();
55
- if (!userAccountExists) {
56
- //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
57
- const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
58
- yield clearingHouse.initializeUserAccountAndDepositCollateral(depositAmount, yield exports.getTokenAddress(usdcTokenAddress.toString(), wallet.publicKey.toString()), banks_1.Banks['devnet'][0].bankIndex);
59
- }
60
- yield user.subscribe();
61
- // Get current price
62
- const solMarketInfo = sdkConfig.MARKETS.find((market) => market.baseAssetSymbol === 'SOL');
63
- const currentMarketPrice = __2.calculateMarkPrice(clearingHouse.getMarketAccount(solMarketInfo.marketIndex), undefined);
64
- const formattedPrice = __2.convertToNumber(currentMarketPrice, __2.MARK_PRICE_PRECISION);
65
- console.log(`Current Market Price is $${formattedPrice}`);
66
- // Estimate the slippage for a $5000 LONG trade
67
- const solMarketAccount = clearingHouse.getMarketAccount(solMarketInfo.marketIndex);
68
- const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
69
- const slippage = __2.convertToNumber(__2.calculateTradeSlippage(__2.PositionDirection.LONG, longAmount, solMarketAccount, 'quote', undefined)[0], __2.MARK_PRICE_PRECISION);
70
- console.log(`Slippage for a $5000 LONG on the SOL market would be $${slippage}`);
71
- // Make a $5000 LONG trade
72
- yield clearingHouse.openPosition(__2.PositionDirection.LONG, longAmount, solMarketInfo.marketIndex);
73
- console.log(`LONGED $5000 SOL`);
74
- // Reduce the position by $2000
75
- const reduceAmount = new anchor_1.BN(2000).mul(__2.QUOTE_PRECISION);
76
- yield clearingHouse.openPosition(__2.PositionDirection.SHORT, reduceAmount, solMarketInfo.marketIndex);
77
- // Close the rest of the position
78
- yield clearingHouse.closePosition(solMarketInfo.marketIndex);
79
- });
52
+ const main = () =>
53
+ __awaiter(void 0, void 0, void 0, function* () {
54
+ // Initialize Drift SDK
55
+ const sdkConfig = __2.initialize({ env: 'devnet' });
56
+ // Set up the Wallet and Provider
57
+ const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
58
+ const keypair = web3_js_1.Keypair.fromSecretKey(
59
+ Uint8Array.from(JSON.parse(privateKey))
60
+ );
61
+ const wallet = new __1.Wallet(keypair);
62
+ // Set up the Connection
63
+ const rpcAddress = process.env.RPC_ADDRESS; // can use: https://api.devnet.solana.com for devnet; https://api.mainnet-beta.solana.com for mainnet;
64
+ const connection = new web3_js_1.Connection(rpcAddress);
65
+ // Set up the Provider
66
+ const provider = new anchor_1.AnchorProvider(
67
+ connection,
68
+ wallet,
69
+ anchor_1.AnchorProvider.defaultOptions()
70
+ );
71
+ // Check SOL Balance
72
+ const lamportsBalance = yield connection.getBalance(wallet.publicKey);
73
+ console.log('SOL balance:', lamportsBalance / Math.pow(10, 9));
74
+ // Misc. other things to set up
75
+ const usdcTokenAddress = yield exports.getTokenAddress(
76
+ sdkConfig.USDC_MINT_ADDRESS,
77
+ wallet.publicKey.toString()
78
+ );
79
+ // Set up the Drift Clearing House
80
+ const clearingHousePublicKey = new web3_js_1.PublicKey(
81
+ sdkConfig.DRIFT_PROGRAM_ID
82
+ );
83
+ const clearingHouse = new __2.ClearingHouse({
84
+ connection,
85
+ wallet: provider.wallet,
86
+ programID: clearingHousePublicKey,
87
+ });
88
+ yield clearingHouse.subscribe();
89
+ // Set up Clearing House user client
90
+ const user = new __2.ClearingHouseUser({
91
+ clearingHouse,
92
+ userAccountPublicKey: yield clearingHouse.getUserAccountPublicKey(),
93
+ });
94
+ //// Check if clearing house account exists for the current wallet
95
+ const userAccountExists = yield user.exists();
96
+ if (!userAccountExists) {
97
+ //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
98
+ const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
99
+ yield clearingHouse.initializeUserAccountAndDepositCollateral(
100
+ depositAmount,
101
+ yield exports.getTokenAddress(
102
+ usdcTokenAddress.toString(),
103
+ wallet.publicKey.toString()
104
+ ),
105
+ banks_1.SpotMarkets['devnet'][0].marketIndex
106
+ );
107
+ }
108
+ yield user.subscribe();
109
+ // Get current price
110
+ const solMarketInfo = sdkConfig.PERP_MARKETS.find(
111
+ (market) => market.baseAssetSymbol === 'SOL'
112
+ );
113
+ const currentMarketPrice = __2.calculateMarkPrice(
114
+ clearingHouse.getMarketAccount(solMarketInfo.marketIndex),
115
+ undefined
116
+ );
117
+ const formattedPrice = __2.convertToNumber(
118
+ currentMarketPrice,
119
+ __2.PRICE_PRECISION
120
+ );
121
+ console.log(`Current Market Price is $${formattedPrice}`);
122
+ // Estimate the slippage for a $5000 LONG trade
123
+ const solMarketAccount = clearingHouse.getMarketAccount(
124
+ solMarketInfo.marketIndex
125
+ );
126
+ const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
127
+ const slippage = __2.convertToNumber(
128
+ __2.calculateTradeSlippage(
129
+ __2.PositionDirection.LONG,
130
+ longAmount,
131
+ solMarketAccount,
132
+ 'quote',
133
+ undefined
134
+ )[0],
135
+ __2.PRICE_PRECISION
136
+ );
137
+ console.log(
138
+ `Slippage for a $5000 LONG on the SOL market would be $${slippage}`
139
+ );
140
+ // Make a $5000 LONG trade
141
+ yield clearingHouse.openPosition(
142
+ __2.PositionDirection.LONG,
143
+ longAmount,
144
+ solMarketInfo.marketIndex
145
+ );
146
+ console.log(`LONGED $5000 SOL`);
147
+ // Reduce the position by $2000
148
+ const reduceAmount = new anchor_1.BN(2000).mul(__2.QUOTE_PRECISION);
149
+ yield clearingHouse.openPosition(
150
+ __2.PositionDirection.SHORT,
151
+ reduceAmount,
152
+ solMarketInfo.marketIndex
153
+ );
154
+ // Close the rest of the position
155
+ yield clearingHouse.closePosition(solMarketInfo.marketIndex);
156
+ });
80
157
  main();