@drift-labs/sdk 0.2.0-master.3 → 0.2.0-master.30

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 (208) hide show
  1. package/README.md +13 -13
  2. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  3. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  4. package/lib/accounts/bulkUserSubscription.js +0 -1
  5. package/lib/accounts/fetch.d.ts +2 -1
  6. package/lib/accounts/fetch.js +9 -1
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +16 -16
  8. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +31 -28
  9. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  10. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  11. package/lib/accounts/types.d.ts +22 -11
  12. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +17 -17
  13. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +37 -35
  14. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  15. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  16. package/lib/addresses/marketAddresses.d.ts +1 -3
  17. package/lib/addresses/pda.d.ts +10 -4
  18. package/lib/addresses/pda.js +51 -14
  19. package/lib/admin.d.ts +34 -22
  20. package/lib/admin.js +182 -73
  21. package/lib/clearingHouse.d.ts +120 -42
  22. package/lib/clearingHouse.js +1505 -254
  23. package/lib/clearingHouseConfig.d.ts +4 -4
  24. package/lib/clearingHouseUser.d.ts +50 -38
  25. package/lib/clearingHouseUser.js +410 -190
  26. package/lib/clearingHouseUserStats.d.ts +18 -0
  27. package/lib/clearingHouseUserStats.js +49 -0
  28. package/lib/clearingHouseUserStatsConfig.d.ts +14 -0
  29. package/lib/clearingHouseUserStatsConfig.js +2 -0
  30. package/lib/config.d.ts +7 -9
  31. package/lib/config.js +21 -21
  32. package/lib/constants/numericConstants.d.ts +18 -12
  33. package/lib/constants/numericConstants.js +28 -21
  34. package/lib/constants/perpMarkets.d.ts +18 -0
  35. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  36. package/lib/constants/spotMarkets.d.ts +19 -0
  37. package/lib/constants/spotMarkets.js +53 -0
  38. package/lib/dlob/DLOB.d.ts +73 -0
  39. package/lib/dlob/DLOB.js +553 -0
  40. package/lib/dlob/DLOBNode.d.ts +52 -0
  41. package/lib/dlob/DLOBNode.js +82 -0
  42. package/lib/dlob/NodeList.d.ts +26 -0
  43. package/lib/dlob/NodeList.js +138 -0
  44. package/lib/events/eventList.js +3 -0
  45. package/lib/events/eventSubscriber.d.ts +4 -2
  46. package/lib/events/eventSubscriber.js +16 -9
  47. package/lib/events/fetchLogs.d.ts +10 -1
  48. package/lib/events/fetchLogs.js +27 -7
  49. package/lib/events/pollingLogProvider.d.ts +2 -1
  50. package/lib/events/pollingLogProvider.js +6 -2
  51. package/lib/events/sort.js +8 -11
  52. package/lib/events/types.d.ts +7 -2
  53. package/lib/events/types.js +5 -0
  54. package/lib/examples/makeTradeExample.js +20 -8
  55. package/lib/factory/bigNum.d.ts +1 -0
  56. package/lib/factory/bigNum.js +34 -10
  57. package/lib/idl/clearing_house.json +4313 -1433
  58. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  59. package/lib/index.d.ts +21 -6
  60. package/lib/index.js +25 -6
  61. package/lib/math/amm.d.ts +8 -5
  62. package/lib/math/amm.js +68 -46
  63. package/lib/math/auction.js +4 -1
  64. package/lib/math/conversion.js +1 -1
  65. package/lib/math/funding.d.ts +6 -6
  66. package/lib/math/funding.js +11 -10
  67. package/lib/math/insurance.d.ts +4 -0
  68. package/lib/math/insurance.js +27 -0
  69. package/lib/math/margin.d.ts +11 -0
  70. package/lib/math/margin.js +77 -0
  71. package/lib/math/market.d.ts +14 -9
  72. package/lib/math/market.js +69 -7
  73. package/lib/math/oracles.d.ts +4 -0
  74. package/lib/math/oracles.js +36 -8
  75. package/lib/math/orders.d.ts +6 -2
  76. package/lib/math/orders.js +78 -3
  77. package/lib/math/position.d.ts +21 -13
  78. package/lib/math/position.js +76 -36
  79. package/lib/math/repeg.js +14 -5
  80. package/lib/math/spotBalance.d.ts +22 -0
  81. package/lib/math/spotBalance.js +193 -0
  82. package/lib/math/spotMarket.d.ts +4 -0
  83. package/lib/math/spotMarket.js +8 -0
  84. package/lib/math/spotPosition.d.ts +6 -0
  85. package/lib/math/spotPosition.js +23 -0
  86. package/lib/math/trade.d.ts +10 -10
  87. package/lib/math/trade.js +22 -29
  88. package/lib/oracles/pythClient.js +1 -1
  89. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  90. package/lib/oracles/switchboardClient.js +1 -1
  91. package/lib/orderParams.d.ts +14 -5
  92. package/lib/orderParams.js +12 -92
  93. package/lib/serum/serumSubscriber.d.ts +23 -0
  94. package/lib/serum/serumSubscriber.js +41 -0
  95. package/lib/serum/types.d.ts +11 -0
  96. package/lib/serum/types.js +2 -0
  97. package/lib/slot/SlotSubscriber.d.ts +7 -0
  98. package/lib/slot/SlotSubscriber.js +3 -0
  99. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  100. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  101. package/lib/tx/retryTxSender.d.ts +1 -1
  102. package/lib/tx/retryTxSender.js +13 -4
  103. package/lib/tx/types.d.ts +1 -1
  104. package/lib/tx/utils.js +1 -1
  105. package/lib/types.d.ts +474 -123
  106. package/lib/types.js +99 -5
  107. package/lib/userMap/userMap.d.ts +25 -0
  108. package/lib/userMap/userMap.js +73 -0
  109. package/lib/userMap/userStatsMap.d.ts +19 -0
  110. package/lib/userMap/userStatsMap.js +68 -0
  111. package/lib/util/computeUnits.js +1 -1
  112. package/lib/util/getTokenAddress.d.ts +2 -0
  113. package/lib/util/getTokenAddress.js +9 -0
  114. package/package.json +9 -5
  115. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  116. package/src/accounts/bulkUserSubscription.ts +0 -1
  117. package/src/accounts/fetch.ts +27 -2
  118. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +46 -42
  119. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  120. package/src/accounts/types.ts +31 -11
  121. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +64 -59
  122. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  123. package/src/addresses/marketAddresses.ts +1 -2
  124. package/src/addresses/pda.ts +88 -14
  125. package/src/admin.ts +333 -128
  126. package/src/assert/assert.js +9 -0
  127. package/src/clearingHouse.ts +2464 -458
  128. package/src/clearingHouseConfig.ts +4 -3
  129. package/src/clearingHouseUser.ts +747 -291
  130. package/src/clearingHouseUserStats.ts +75 -0
  131. package/src/clearingHouseUserStatsConfig.ts +18 -0
  132. package/src/config.ts +30 -31
  133. package/src/constants/numericConstants.ts +41 -25
  134. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  135. package/src/constants/spotMarkets.ts +72 -0
  136. package/src/dlob/DLOB.ts +868 -0
  137. package/src/dlob/DLOBNode.ts +162 -0
  138. package/src/dlob/NodeList.ts +185 -0
  139. package/src/events/eventList.js +77 -0
  140. package/src/events/eventList.ts +3 -0
  141. package/src/events/eventSubscriber.ts +20 -12
  142. package/src/events/fetchLogs.ts +35 -8
  143. package/src/events/pollingLogProvider.ts +10 -2
  144. package/src/events/sort.ts +11 -15
  145. package/src/events/types.ts +16 -1
  146. package/src/examples/makeTradeExample.js +157 -0
  147. package/src/examples/makeTradeExample.ts +32 -14
  148. package/src/factory/bigNum.ts +42 -13
  149. package/src/idl/clearing_house.json +4313 -1433
  150. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  151. package/src/index.ts +21 -6
  152. package/src/math/amm.ts +136 -66
  153. package/src/math/auction.ts +5 -1
  154. package/src/math/conversion.ts +2 -2
  155. package/src/math/funding.ts +20 -18
  156. package/src/math/insurance.ts +35 -0
  157. package/src/math/margin.ts +127 -0
  158. package/src/math/market.ts +138 -12
  159. package/src/math/oracles.ts +63 -9
  160. package/src/math/orders.ts +138 -4
  161. package/src/math/position.ts +119 -58
  162. package/src/math/repeg.ts +16 -6
  163. package/src/math/spotBalance.ts +316 -0
  164. package/src/math/spotMarket.ts +9 -0
  165. package/src/math/spotPosition.ts +47 -0
  166. package/src/math/trade.ts +43 -49
  167. package/src/oracles/pythClient.ts +2 -2
  168. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  169. package/src/oracles/switchboardClient.ts +2 -2
  170. package/src/orderParams.ts +24 -137
  171. package/src/serum/serumSubscriber.ts +80 -0
  172. package/src/serum/types.ts +13 -0
  173. package/src/slot/SlotSubscriber.ts +11 -1
  174. package/src/token/index.js +38 -0
  175. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  176. package/src/tx/retryTxSender.ts +16 -5
  177. package/src/tx/types.js +2 -0
  178. package/src/tx/types.ts +2 -1
  179. package/src/tx/utils.js +17 -0
  180. package/src/tx/utils.ts +1 -1
  181. package/src/types.ts +477 -125
  182. package/src/userMap/userMap.ts +100 -0
  183. package/src/userMap/userStatsMap.ts +110 -0
  184. package/src/util/computeUnits.js +21 -11
  185. package/src/util/computeUnits.ts +1 -1
  186. package/src/util/getTokenAddress.js +9 -0
  187. package/src/util/getTokenAddress.ts +18 -0
  188. package/src/util/promiseTimeout.js +14 -0
  189. package/src/util/tps.js +27 -0
  190. package/tests/bn/test.ts +12 -3
  191. package/tests/dlob/helpers.ts +374 -0
  192. package/tests/dlob/test.ts +2865 -0
  193. package/lib/constants/banks.d.ts +0 -16
  194. package/lib/constants/banks.js +0 -34
  195. package/lib/constants/markets.d.ts +0 -19
  196. package/lib/math/bankBalance.d.ts +0 -9
  197. package/lib/math/bankBalance.js +0 -75
  198. package/lib/math/state.d.ts +0 -8
  199. package/lib/math/state.js +0 -15
  200. package/lib/orders.d.ts +0 -8
  201. package/lib/orders.js +0 -134
  202. package/src/constants/banks.ts +0 -43
  203. package/src/math/bankBalance.ts +0 -112
  204. package/src/math/state.ts +0 -14
  205. package/src/math/utils.js +0 -27
  206. package/src/math/utils.js.map +0 -1
  207. package/src/orders.ts +0 -244
  208. package/src/util/computeUnits.js.map +0 -1
@@ -0,0 +1,26 @@
1
+ /// <reference types="bn.js" />
2
+ import { BN, MarketTypeStr, Order, PerpMarketAccount, SpotMarketAccount } from '..';
3
+ import { PublicKey } from '@solana/web3.js';
4
+ import { DLOBNode, DLOBNodeMap } from './DLOBNode';
5
+ export declare type SortDirection = 'asc' | 'desc';
6
+ export declare function getOrderSignature(orderId: BN, userAccount: PublicKey): string;
7
+ export interface DLOBNodeGenerator {
8
+ getGenerator(): Generator<DLOBNode>;
9
+ }
10
+ export declare class NodeList<NodeType extends keyof DLOBNodeMap> implements DLOBNodeGenerator {
11
+ private nodeType;
12
+ private sortDirection;
13
+ head?: DLOBNodeMap[NodeType];
14
+ length: number;
15
+ nodeMap: Map<string, DLOBNodeMap[NodeType]>;
16
+ constructor(nodeType: NodeType, sortDirection: SortDirection);
17
+ insert(order: Order, marketType: MarketTypeStr, market: PerpMarketAccount | SpotMarketAccount, userAccount: PublicKey): void;
18
+ prependNode(currentNode: DLOBNodeMap[NodeType], newNode: DLOBNodeMap[NodeType]): boolean;
19
+ update(order: Order, userAccount: PublicKey): void;
20
+ remove(order: Order, userAccount: PublicKey): void;
21
+ getGenerator(): Generator<DLOBNode>;
22
+ has(order: Order, userAccount: PublicKey): boolean;
23
+ print(): void;
24
+ printTop(): void;
25
+ }
26
+ export declare function getVammNodeGenerator(price: BN | undefined): Generator<DLOBNode>;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getVammNodeGenerator = exports.NodeList = exports.getOrderSignature = void 0;
4
+ const __1 = require("..");
5
+ const DLOBNode_1 = require("./DLOBNode");
6
+ function getOrderSignature(orderId, userAccount) {
7
+ return `${userAccount.toString()}-${orderId.toString()}`;
8
+ }
9
+ exports.getOrderSignature = getOrderSignature;
10
+ class NodeList {
11
+ constructor(nodeType, sortDirection) {
12
+ this.nodeType = nodeType;
13
+ this.sortDirection = sortDirection;
14
+ this.length = 0;
15
+ this.nodeMap = new Map();
16
+ }
17
+ insert(order, marketType, market, userAccount) {
18
+ if ((0, __1.isVariant)(order.status, 'init')) {
19
+ return;
20
+ }
21
+ if (marketType === 'spot') {
22
+ market = market;
23
+ }
24
+ else if (marketType === 'perp') {
25
+ market = market;
26
+ }
27
+ const newNode = (0, DLOBNode_1.createNode)(this.nodeType, order, market, userAccount);
28
+ const orderId = getOrderSignature(order.orderId, userAccount);
29
+ if (this.nodeMap.has(orderId)) {
30
+ return;
31
+ }
32
+ this.nodeMap.set(orderId, newNode);
33
+ this.length += 1;
34
+ if (this.head === undefined) {
35
+ this.head = newNode;
36
+ return;
37
+ }
38
+ if (this.prependNode(this.head, newNode)) {
39
+ this.head.previous = newNode;
40
+ newNode.next = this.head;
41
+ this.head = newNode;
42
+ return;
43
+ }
44
+ let currentNode = this.head;
45
+ while (currentNode.next !== undefined &&
46
+ !this.prependNode(currentNode.next, newNode)) {
47
+ currentNode = currentNode.next;
48
+ }
49
+ newNode.next = currentNode.next;
50
+ if (currentNode.next !== undefined) {
51
+ newNode.next.previous = newNode;
52
+ }
53
+ currentNode.next = newNode;
54
+ newNode.previous = currentNode;
55
+ }
56
+ prependNode(currentNode, newNode) {
57
+ const currentOrder = currentNode.order;
58
+ const newOrder = newNode.order;
59
+ const currentOrderSortPrice = currentNode.sortValue;
60
+ const newOrderSortPrice = newNode.sortValue;
61
+ if (newOrderSortPrice.eq(currentOrderSortPrice)) {
62
+ return newOrder.ts.lt(currentOrder.ts);
63
+ }
64
+ if (this.sortDirection === 'asc') {
65
+ return newOrderSortPrice.lt(currentOrderSortPrice);
66
+ }
67
+ else {
68
+ return newOrderSortPrice.gt(currentOrderSortPrice);
69
+ }
70
+ }
71
+ update(order, userAccount) {
72
+ const orderId = getOrderSignature(order.orderId, userAccount);
73
+ if (this.nodeMap.has(orderId)) {
74
+ const node = this.nodeMap.get(orderId);
75
+ Object.assign(node.order, order);
76
+ node.haveFilled = false;
77
+ }
78
+ }
79
+ remove(order, userAccount) {
80
+ const orderId = getOrderSignature(order.orderId, userAccount);
81
+ if (this.nodeMap.has(orderId)) {
82
+ const node = this.nodeMap.get(orderId);
83
+ if (node.next) {
84
+ node.next.previous = node.previous;
85
+ }
86
+ if (node.previous) {
87
+ node.previous.next = node.next;
88
+ }
89
+ if (this.head && node.order.orderId.eq(this.head.order.orderId)) {
90
+ this.head = node.next;
91
+ }
92
+ node.previous = undefined;
93
+ node.next = undefined;
94
+ this.nodeMap.delete(orderId);
95
+ this.length--;
96
+ }
97
+ }
98
+ *getGenerator() {
99
+ let node = this.head;
100
+ while (node !== undefined) {
101
+ yield node;
102
+ node = node.next;
103
+ }
104
+ }
105
+ has(order, userAccount) {
106
+ return this.nodeMap.has(getOrderSignature(order.orderId, userAccount));
107
+ }
108
+ print() {
109
+ let currentNode = this.head;
110
+ while (currentNode !== undefined) {
111
+ console.log(currentNode.getLabel());
112
+ currentNode = currentNode.next;
113
+ }
114
+ }
115
+ printTop() {
116
+ if (this.head) {
117
+ console.log(this.sortDirection.toUpperCase(), this.head.getLabel());
118
+ }
119
+ else {
120
+ console.log('---');
121
+ }
122
+ }
123
+ }
124
+ exports.NodeList = NodeList;
125
+ function* getVammNodeGenerator(price) {
126
+ if (!price) {
127
+ return;
128
+ }
129
+ yield {
130
+ getPrice: () => price,
131
+ isVammNode: () => true,
132
+ order: undefined,
133
+ market: undefined,
134
+ userAccount: undefined,
135
+ haveFilled: false,
136
+ };
137
+ }
138
+ exports.getVammNodeGenerator = getVammNodeGenerator;
@@ -40,6 +40,9 @@ class EventList {
40
40
  if (currentNode.next !== undefined) {
41
41
  newNode.next.prev = newNode;
42
42
  }
43
+ else {
44
+ this.tail = newNode;
45
+ }
43
46
  currentNode.next = newNode;
44
47
  newNode.prev = currentNode;
45
48
  }
@@ -15,10 +15,12 @@ export declare class EventSubscriber {
15
15
  private awaitTxResolver;
16
16
  private logProvider;
17
17
  eventEmitter: StrictEventEmitter<EventEmitter, EventSubscriberEvents>;
18
+ private lastSeenSlot;
19
+ lastSeenTxSig: string;
18
20
  constructor(connection: Connection, program: Program, options?: EventSubscriptionOptions);
19
- subscribe(): boolean;
21
+ subscribe(): Promise<boolean>;
20
22
  private handleTxLogs;
21
- private fetchPreviousTx;
23
+ fetchPreviousTx(fetchMax?: boolean): Promise<void>;
22
24
  unsubscribe(): Promise<boolean>;
23
25
  private parseEventsFromLogs;
24
26
  awaitTx(txSig: TransactionSignature): Promise<void>;
@@ -30,17 +30,21 @@ class EventSubscriber {
30
30
  this.logProvider = new pollingLogProvider_1.PollingLogProvider(this.connection, this.program.programId, options.commitment, this.options.logProviderConfig.frequency);
31
31
  }
32
32
  }
33
- subscribe() {
34
- if (this.logProvider.isSubscribed()) {
33
+ async subscribe() {
34
+ try {
35
+ if (this.logProvider.isSubscribed()) {
36
+ return true;
37
+ }
38
+ this.logProvider.subscribe((txSig, slot, logs) => {
39
+ this.handleTxLogs(txSig, slot, logs);
40
+ }, true);
35
41
  return true;
36
42
  }
37
- this.fetchPreviousTx().catch((e) => {
43
+ catch (e) {
38
44
  console.error('Error fetching previous txs in event subscriber');
39
45
  console.error(e);
40
- });
41
- return this.logProvider.subscribe((txSig, slot, logs) => {
42
- this.handleTxLogs(txSig, slot, logs);
43
- });
46
+ return false;
47
+ }
44
48
  }
45
49
  handleTxLogs(txSig, slot, logs) {
46
50
  if (this.txEventCache.has(txSig)) {
@@ -56,10 +60,13 @@ class EventSubscriber {
56
60
  this.awaitTxResolver.get(txSig)();
57
61
  this.awaitTxResolver.delete(txSig);
58
62
  }
63
+ if (slot > this.lastSeenSlot) {
64
+ this.lastSeenTxSig = txSig;
65
+ }
59
66
  this.txEventCache.add(txSig, wrappedEvents);
60
67
  }
61
- async fetchPreviousTx() {
62
- if (!this.options.untilTx) {
68
+ async fetchPreviousTx(fetchMax) {
69
+ if (!this.options.untilTx && !fetchMax) {
63
70
  return;
64
71
  }
65
72
  let txFetched = 0;
@@ -1,4 +1,6 @@
1
+ import { Program } from '@project-serum/anchor';
1
2
  import { Connection, Finality, PublicKey, TransactionSignature } from '@solana/web3.js';
3
+ import { WrappedEvents } from './types';
2
4
  declare type Log = {
3
5
  txSig: TransactionSignature;
4
6
  slot: number;
@@ -7,7 +9,14 @@ declare type Log = {
7
9
  declare type FetchLogsResponse = {
8
10
  earliestTx: string;
9
11
  mostRecentTx: string;
12
+ earliestSlot: number;
13
+ mostRecentSlot: number;
10
14
  transactionLogs: Log[];
11
15
  };
12
- export declare function fetchLogs(connection: Connection, programId: PublicKey, finality: Finality, beforeTx?: TransactionSignature, untilTx?: TransactionSignature): Promise<FetchLogsResponse | undefined>;
16
+ export declare function fetchLogs(connection: Connection, programId: PublicKey, finality: Finality, beforeTx?: TransactionSignature, untilTx?: TransactionSignature, limit?: number): Promise<FetchLogsResponse>;
17
+ export declare class LogParser {
18
+ private program;
19
+ constructor(program: Program);
20
+ parseEventsFromLogs(event: Log): WrappedEvents;
21
+ }
13
22
  export {};
@@ -1,12 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fetchLogs = void 0;
4
- async function fetchLogs(connection, programId, finality, beforeTx, untilTx) {
3
+ exports.LogParser = exports.fetchLogs = void 0;
4
+ async function fetchLogs(connection, programId, finality, beforeTx, untilTx, limit) {
5
5
  const signatures = await connection.getSignaturesForAddress(programId, {
6
6
  before: beforeTx,
7
7
  until: untilTx,
8
+ limit,
8
9
  }, finality);
9
- const sortedSignatures = signatures.sort((a, b) => a.slot < b.slot ? -1 : 1);
10
+ const sortedSignatures = signatures.sort((a, b) => a.slot === b.slot ? 0 : a.slot < b.slot ? -1 : 1);
10
11
  const filteredSignatures = sortedSignatures.filter((signature) => !signature.err);
11
12
  if (filteredSignatures.length === 0) {
12
13
  return undefined;
@@ -22,12 +23,14 @@ async function fetchLogs(connection, programId, finality, beforeTx, untilTx) {
22
23
  };
23
24
  });
24
25
  }))).flat();
25
- const earliestTx = filteredSignatures[0].signature;
26
- const mostRecentTx = filteredSignatures[filteredSignatures.length - 1].signature;
26
+ const earliest = filteredSignatures[0];
27
+ const mostRecent = filteredSignatures[filteredSignatures.length - 1];
27
28
  return {
28
29
  transactionLogs: transactionLogs,
29
- earliestTx: earliestTx,
30
- mostRecentTx: mostRecentTx,
30
+ earliestTx: earliest.signature,
31
+ mostRecentTx: mostRecent.signature,
32
+ earliestSlot: earliest.slot,
33
+ mostRecentSlot: mostRecent.slot,
31
34
  };
32
35
  }
33
36
  exports.fetchLogs = fetchLogs;
@@ -37,3 +40,20 @@ function chunk(array, size) {
37
40
  .map((_, index) => index * size)
38
41
  .map((begin) => array.slice(begin, begin + size));
39
42
  }
43
+ class LogParser {
44
+ constructor(program) {
45
+ this.program = program;
46
+ }
47
+ parseEventsFromLogs(event) {
48
+ const records = [];
49
+ // @ts-ignore
50
+ this.program._events._eventParser.parseLogs(event.logs, (eventLog) => {
51
+ eventLog.data.txSig = event.txSig;
52
+ eventLog.data.slot = event.slot;
53
+ eventLog.data.eventType = eventLog.name;
54
+ records.push(eventLog.data);
55
+ });
56
+ return records;
57
+ }
58
+ }
59
+ exports.LogParser = LogParser;
@@ -8,8 +8,9 @@ export declare class PollingLogProvider implements LogProvider {
8
8
  private intervalId;
9
9
  private mostRecentSeenTx?;
10
10
  private mutex;
11
+ private firstFetch;
11
12
  constructor(connection: Connection, programId: PublicKey, commitment: Commitment, frequency?: number);
12
- subscribe(callback: logProviderCallback): boolean;
13
+ subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
13
14
  isSubscribed(): boolean;
14
15
  unsubscribe(): Promise<boolean>;
15
16
  }
@@ -7,9 +7,10 @@ class PollingLogProvider {
7
7
  this.connection = connection;
8
8
  this.programId = programId;
9
9
  this.frequency = frequency;
10
+ this.firstFetch = true;
10
11
  this.finality = commitment === 'finalized' ? 'finalized' : 'confirmed';
11
12
  }
12
- subscribe(callback) {
13
+ subscribe(callback, skipHistory) {
13
14
  if (this.intervalId) {
14
15
  return true;
15
16
  }
@@ -19,7 +20,10 @@ class PollingLogProvider {
19
20
  }
20
21
  this.mutex = 1;
21
22
  try {
22
- const response = await (0, fetchLogs_1.fetchLogs)(this.connection, this.programId, this.finality, undefined, this.mostRecentSeenTx);
23
+ const response = await (0, fetchLogs_1.fetchLogs)(this.connection, this.programId, this.finality, undefined, this.mostRecentSeenTx,
24
+ // If skipping history, only fetch one log back, not the maximum amount available
25
+ skipHistory && this.firstFetch ? 1 : undefined);
26
+ this.firstFetch = false;
23
27
  if (response === undefined) {
24
28
  return;
25
29
  }
@@ -11,17 +11,14 @@ function clientSortDescFn() {
11
11
  function defaultBlockchainSortFn(currentEvent, newEvent) {
12
12
  return currentEvent.slot <= newEvent.slot ? 'less than' : 'greater than';
13
13
  }
14
- function orderRecordSortFn(currentEvent, newEvent) {
15
- const currentEventMarketIndex = !currentEvent.maker.equals(index_1.PublicKey.default)
16
- ? currentEvent.makerOrder.marketIndex
17
- : currentEvent.takerOrder.marketIndex;
18
- const newEventMarketIndex = !newEvent.maker.equals(index_1.PublicKey.default)
19
- ? newEvent.makerOrder.marketIndex
20
- : newEvent.takerOrder.marketIndex;
21
- if (!currentEventMarketIndex.eq(newEventMarketIndex)) {
14
+ function orderActionRecordSortFn(currentEvent, newEvent) {
15
+ var _a, _b;
16
+ const currentEventMarketIndex = currentEvent.marketIndex;
17
+ const newEventMarketIndex = newEvent.marketIndex;
18
+ if (currentEventMarketIndex !== newEventMarketIndex) {
22
19
  return currentEvent.ts.lte(newEvent.ts) ? 'less than' : 'greater than';
23
20
  }
24
- if (currentEvent.fillRecordId.gt(index_1.ZERO) && newEvent.fillRecordId.gt(index_1.ZERO)) {
21
+ if (((_a = currentEvent.fillRecordId) === null || _a === void 0 ? void 0 : _a.gt(index_1.ZERO)) && ((_b = newEvent.fillRecordId) === null || _b === void 0 ? void 0 : _b.gt(index_1.ZERO))) {
25
22
  return currentEvent.fillRecordId.lte(newEvent.fillRecordId)
26
23
  ? 'less than'
27
24
  : 'greater than';
@@ -35,8 +32,8 @@ function getSortFn(orderBy, orderDir, eventType) {
35
32
  return orderDir === 'asc' ? clientSortAscFn : clientSortDescFn;
36
33
  }
37
34
  switch (eventType) {
38
- case 'OrderRecord':
39
- return orderRecordSortFn;
35
+ case 'OrderActionRecord':
36
+ return orderActionRecordSortFn;
40
37
  default:
41
38
  return defaultBlockchainSortFn;
42
39
  }
@@ -1,5 +1,5 @@
1
1
  import { Commitment, TransactionSignature } from '@solana/web3.js';
2
- import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, OrderRecord } from '../index';
2
+ import { DepositRecord, FundingPaymentRecord, FundingRateRecord, LiquidationRecord, NewUserRecord, OrderActionRecord, OrderRecord, SettlePnlRecord, LPRecord, InsuranceFundRecord } from '../index';
3
3
  export declare type EventSubscriptionOptions = {
4
4
  eventTypes?: EventType[];
5
5
  maxEventsPerType?: number;
@@ -27,6 +27,11 @@ export declare type EventMap = {
27
27
  LiquidationRecord: Event<LiquidationRecord>;
28
28
  FundingRateRecord: Event<FundingRateRecord>;
29
29
  OrderRecord: Event<OrderRecord>;
30
+ OrderActionRecord: Event<OrderActionRecord>;
31
+ SettlePnlRecord: Event<SettlePnlRecord>;
32
+ NewUserRecord: Event<NewUserRecord>;
33
+ LPRecord: Event<LPRecord>;
34
+ InsuranceFundRecord: Event<InsuranceFundRecord>;
30
35
  };
31
36
  export declare type EventType = keyof EventMap;
32
37
  export interface EventSubscriberEvents {
@@ -36,7 +41,7 @@ export declare type SortFn = (currentRecord: EventMap[EventType], newRecord: Eve
36
41
  export declare type logProviderCallback = (txSig: TransactionSignature, slot: number, logs: string[]) => void;
37
42
  export interface LogProvider {
38
43
  isSubscribed(): boolean;
39
- subscribe(callback: logProviderCallback): boolean;
44
+ subscribe(callback: logProviderCallback, skipHistory?: boolean): boolean;
40
45
  unsubscribe(): Promise<boolean>;
41
46
  }
42
47
  export declare type WebSocketLogProviderConfig = {
@@ -7,7 +7,12 @@ exports.DefaultEventSubscriptionOptions = {
7
7
  'FundingPaymentRecord',
8
8
  'LiquidationRecord',
9
9
  'OrderRecord',
10
+ 'OrderActionRecord',
10
11
  'FundingRateRecord',
12
+ 'NewUserRecord',
13
+ 'SettlePnlRecord',
14
+ 'LPRecord',
15
+ 'InsuranceFundRecord',
11
16
  ],
12
17
  maxEventsPerType: 4096,
13
18
  orderBy: 'blockchain',
@@ -6,14 +6,15 @@ const __1 = require("..");
6
6
  const spl_token_1 = require("@solana/spl-token");
7
7
  const web3_js_1 = require("@solana/web3.js");
8
8
  const __2 = require("..");
9
- const banks_1 = require("../constants/banks");
9
+ const spotMarkets_1 = require("../constants/spotMarkets");
10
10
  const getTokenAddress = (mintAddress, userPubKey) => {
11
11
  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));
12
12
  };
13
13
  exports.getTokenAddress = getTokenAddress;
14
+ const cluster = 'devnet';
14
15
  const main = async () => {
15
16
  // Initialize Drift SDK
16
- const sdkConfig = (0, __2.initialize)({ env: 'devnet' });
17
+ const sdkConfig = (0, __2.initialize)({ env: cluster });
17
18
  // Set up the Wallet and Provider
18
19
  const privateKey = process.env.BOT_PRIVATE_KEY; // stored as an array string
19
20
  const keypair = web3_js_1.Keypair.fromSecretKey(Uint8Array.from(JSON.parse(privateKey)));
@@ -30,34 +31,45 @@ const main = async () => {
30
31
  const usdcTokenAddress = await (0, exports.getTokenAddress)(sdkConfig.USDC_MINT_ADDRESS, wallet.publicKey.toString());
31
32
  // Set up the Drift Clearing House
32
33
  const clearingHousePublicKey = new web3_js_1.PublicKey(sdkConfig.CLEARING_HOUSE_PROGRAM_ID);
34
+ const bulkAccountLoader = new __2.BulkAccountLoader(connection, 'confirmed', 1000);
33
35
  const clearingHouse = new __2.ClearingHouse({
34
36
  connection,
35
37
  wallet: provider.wallet,
36
38
  programID: clearingHousePublicKey,
39
+ perpMarketIndexes: __2.PerpMarkets[cluster].map((market) => market.marketIndex),
40
+ spotMarketIndexes: spotMarkets_1.SpotMarkets[cluster].map((spotMarket) => spotMarket.marketIndex),
41
+ accountSubscription: {
42
+ type: 'polling',
43
+ accountLoader: bulkAccountLoader,
44
+ },
37
45
  });
38
46
  await clearingHouse.subscribe();
39
47
  // Set up Clearing House user client
40
48
  const user = new __2.ClearingHouseUser({
41
49
  clearingHouse,
42
50
  userAccountPublicKey: await clearingHouse.getUserAccountPublicKey(),
51
+ accountSubscription: {
52
+ type: 'polling',
53
+ accountLoader: bulkAccountLoader,
54
+ },
43
55
  });
44
56
  //// Check if clearing house account exists for the current wallet
45
57
  const userAccountExists = await user.exists();
46
58
  if (!userAccountExists) {
47
59
  //// Create a Clearing House account by Depositing some USDC ($10,000 in this case)
48
60
  const depositAmount = new anchor_1.BN(10000).mul(__2.QUOTE_PRECISION);
49
- await clearingHouse.initializeUserAccountAndDepositCollateral(depositAmount, await (0, exports.getTokenAddress)(usdcTokenAddress.toString(), wallet.publicKey.toString()), banks_1.Banks['devnet'][0].bankIndex);
61
+ await clearingHouse.initializeUserAccountAndDepositCollateral(depositAmount, await (0, exports.getTokenAddress)(usdcTokenAddress.toString(), wallet.publicKey.toString()), spotMarkets_1.SpotMarkets['devnet'][0].marketIndex);
50
62
  }
51
63
  await user.subscribe();
52
64
  // Get current price
53
- const solMarketInfo = sdkConfig.MARKETS.find((market) => market.baseAssetSymbol === 'SOL');
54
- const currentMarketPrice = (0, __2.calculateMarkPrice)(clearingHouse.getMarketAccount(solMarketInfo.marketIndex), undefined);
55
- const formattedPrice = (0, __2.convertToNumber)(currentMarketPrice, __2.MARK_PRICE_PRECISION);
65
+ const solMarketInfo = sdkConfig.PERP_MARKETS.find((market) => market.baseAssetSymbol === 'SOL');
66
+ const currentMarketPrice = (0, __2.calculateReservePrice)(clearingHouse.getPerpMarketAccount(solMarketInfo.marketIndex), undefined);
67
+ const formattedPrice = (0, __2.convertToNumber)(currentMarketPrice, __2.PRICE_PRECISION);
56
68
  console.log(`Current Market Price is $${formattedPrice}`);
57
69
  // Estimate the slippage for a $5000 LONG trade
58
- const solMarketAccount = clearingHouse.getMarketAccount(solMarketInfo.marketIndex);
70
+ const solMarketAccount = clearingHouse.getPerpMarketAccount(solMarketInfo.marketIndex);
59
71
  const longAmount = new anchor_1.BN(5000).mul(__2.QUOTE_PRECISION);
60
- const slippage = (0, __2.convertToNumber)((0, __2.calculateTradeSlippage)(__2.PositionDirection.LONG, longAmount, solMarketAccount, 'quote', undefined)[0], __2.MARK_PRICE_PRECISION);
72
+ const slippage = (0, __2.convertToNumber)((0, __2.calculateTradeSlippage)(__2.PositionDirection.LONG, longAmount, solMarketAccount, 'quote', undefined)[0], __2.PRICE_PRECISION);
61
73
  console.log(`Slippage for a $5000 LONG on the SOL market would be $${slippage}`);
62
74
  // Make a $5000 LONG trade
63
75
  await clearingHouse.openPosition(__2.PositionDirection.LONG, longAmount, solMarketInfo.marketIndex);
@@ -6,6 +6,7 @@ export declare class BigNum {
6
6
  static delim: string;
7
7
  static spacer: string;
8
8
  constructor(val: BN | number | string, precisionVal?: BN | number | string);
9
+ private bigNumFromParam;
9
10
  add(bn: BigNum): BigNum;
10
11
  sub(bn: BigNum): BigNum;
11
12
  mul(bn: BigNum | BN): BigNum;
@@ -10,6 +10,9 @@ class BigNum {
10
10
  this.val = new anchor_1.BN(val);
11
11
  this.precision = new anchor_1.BN(precisionVal);
12
12
  }
13
+ bigNumFromParam(bn) {
14
+ return anchor_1.BN.isBN(bn) ? BigNum.from(bn) : bn;
15
+ }
13
16
  add(bn) {
14
17
  (0, assert_1.assert)(bn.precision.eq(this.precision), 'Adding unequal precisions');
15
18
  return BigNum.from(this.val.add(bn.val), this.precision);
@@ -19,7 +22,7 @@ class BigNum {
19
22
  return BigNum.from(this.val.sub(bn.val), this.precision);
20
23
  }
21
24
  mul(bn) {
22
- const mulVal = bn instanceof BigNum ? bn : BigNum.from(bn);
25
+ const mulVal = this.bigNumFromParam(bn);
23
26
  return BigNum.from(this.val.mul(mulVal.val), this.precision.add(mulVal.precision));
24
27
  }
25
28
  /**
@@ -28,12 +31,12 @@ class BigNum {
28
31
  * @returns
29
32
  */
30
33
  scalarMul(bn) {
31
- if (bn instanceof anchor_1.BN)
34
+ if (anchor_1.BN.isBN(bn))
32
35
  return BigNum.from(this.val.mul(bn), this.precision);
33
36
  return BigNum.from(this.val.mul(bn.val), this.precision.add(bn.precision)).shift(bn.precision.neg());
34
37
  }
35
38
  div(bn) {
36
- if (bn instanceof anchor_1.BN)
39
+ if (anchor_1.BN.isBN(bn))
37
40
  return BigNum.from(this.val.div(bn), this.precision);
38
41
  return BigNum.from(this.val.div(bn.val), this.precision.sub(bn.precision));
39
42
  }
@@ -73,35 +76,35 @@ class BigNum {
73
76
  .toPrecision(precision);
74
77
  }
75
78
  gt(bn, ignorePrecision) {
76
- const comparisonVal = bn instanceof BigNum ? bn : BigNum.from(bn);
79
+ const comparisonVal = this.bigNumFromParam(bn);
77
80
  if (!ignorePrecision && !comparisonVal.eq(numericConstants_1.ZERO)) {
78
81
  (0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
79
82
  }
80
83
  return this.val.gt(comparisonVal.val);
81
84
  }
82
85
  lt(bn, ignorePrecision) {
83
- const comparisonVal = bn instanceof BigNum ? bn : BigNum.from(bn);
86
+ const comparisonVal = this.bigNumFromParam(bn);
84
87
  if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
85
88
  (0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
86
89
  }
87
90
  return this.val.lt(comparisonVal.val);
88
91
  }
89
92
  gte(bn, ignorePrecision) {
90
- const comparisonVal = bn instanceof BigNum ? bn : BigNum.from(bn);
93
+ const comparisonVal = this.bigNumFromParam(bn);
91
94
  if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
92
95
  (0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
93
96
  }
94
97
  return this.val.gte(comparisonVal.val);
95
98
  }
96
99
  lte(bn, ignorePrecision) {
97
- const comparisonVal = bn instanceof BigNum ? bn : BigNum.from(bn);
100
+ const comparisonVal = this.bigNumFromParam(bn);
98
101
  if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
99
102
  (0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
100
103
  }
101
104
  return this.val.lte(comparisonVal.val);
102
105
  }
103
106
  eq(bn, ignorePrecision) {
104
- const comparisonVal = bn instanceof BigNum ? bn : BigNum.from(bn);
107
+ const comparisonVal = this.bigNumFromParam(bn);
105
108
  if (!ignorePrecision && !comparisonVal.val.eq(numericConstants_1.ZERO)) {
106
109
  (0, assert_1.assert)(comparisonVal.precision.eq(this.precision), 'Trying to compare numbers with different precision. Yo can opt to ignore precision using the ignorePrecision parameter');
107
110
  }
@@ -134,7 +137,8 @@ class BigNum {
134
137
  */
135
138
  print() {
136
139
  (0, assert_1.assert)(this.precision.gte(numericConstants_1.ZERO), 'Tried to print a BN with precision lower than zero');
137
- const plainString = this.toString();
140
+ const isNeg = this.isNeg();
141
+ const plainString = this.abs().toString();
138
142
  const precisionNum = this.precision.toNumber();
139
143
  // make a string with at least the precisionNum number of zeroes
140
144
  let printString = [
@@ -151,6 +155,9 @@ class BigNum {
151
155
  // add zero if leading delim
152
156
  if (printString[0] === BigNum.delim)
153
157
  printString = `0${printString}`;
158
+ // Add minus if negative
159
+ if (isNeg)
160
+ printString = `-${printString}`;
154
161
  // remove trailing delim
155
162
  if (printString[printString.length - 1] === BigNum.delim)
156
163
  printString = printString.slice(0, printString.length - 1);
@@ -261,10 +268,27 @@ class BigNum {
261
268
  * @returns
262
269
  */
263
270
  toNotional(useTradePrecision, precisionOverride) {
271
+ var _a;
264
272
  const prefix = `${this.lt(BigNum.zero()) ? `-` : ``}$`;
265
- const val = useTradePrecision || precisionOverride
273
+ const usingCustomPrecision = true && (useTradePrecision || precisionOverride);
274
+ let val = usingCustomPrecision
266
275
  ? this.prettyPrint(useTradePrecision, precisionOverride)
267
276
  : BigNum.fromPrint(this.toFixed(2), new anchor_1.BN(2)).prettyPrint();
277
+ // Append two trailing zeroes if not using custom precision
278
+ if (!usingCustomPrecision) {
279
+ const [_, rightSide] = val.split(BigNum.delim);
280
+ const trailingLength = (_a = rightSide === null || rightSide === void 0 ? void 0 : rightSide.length) !== null && _a !== void 0 ? _a : 0;
281
+ if (trailingLength < 2) {
282
+ const numHasDecimals = this.print().includes(BigNum.delim);
283
+ // Handle case where pretty print won't include the decimal point
284
+ if (trailingLength === 0 && numHasDecimals) {
285
+ val = `${val}.00`;
286
+ }
287
+ else {
288
+ val = `${val}${new Array(2 - trailingLength).fill('0').join('')}`;
289
+ }
290
+ }
291
+ }
268
292
  return `${prefix}${val.replace('-', '')}`;
269
293
  }
270
294
  toMillified(precision = 3) {