@drift-labs/sdk 0.1.36-master.7 → 0.2.0-master.10

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 (254) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +6 -6
  2. package/lib/accounts/bulkAccountLoader.js +81 -95
  3. package/lib/accounts/bulkUserSubscription.js +13 -57
  4. package/lib/accounts/fetch.d.ts +4 -0
  5. package/lib/accounts/fetch.js +18 -0
  6. package/lib/accounts/pollingClearingHouseAccountSubscriber.d.ts +34 -38
  7. package/lib/accounts/pollingClearingHouseAccountSubscriber.js +224 -224
  8. package/lib/accounts/pollingOracleSubscriber.d.ts +3 -3
  9. package/lib/accounts/pollingOracleSubscriber.js +37 -49
  10. package/lib/accounts/pollingTokenAccountSubscriber.d.ts +3 -3
  11. package/lib/accounts/pollingTokenAccountSubscriber.js +35 -50
  12. package/lib/accounts/pollingUserAccountSubscriber.d.ts +7 -13
  13. package/lib/accounts/pollingUserAccountSubscriber.js +71 -134
  14. package/lib/accounts/types.d.ts +34 -41
  15. package/lib/accounts/webSocketAccountSubscriber.d.ts +6 -4
  16. package/lib/accounts/webSocketAccountSubscriber.js +39 -35
  17. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +33 -28
  18. package/lib/accounts/webSocketClearingHouseAccountSubscriber.js +153 -185
  19. package/lib/accounts/webSocketUserAccountSubscriber.d.ts +5 -11
  20. package/lib/accounts/webSocketUserAccountSubscriber.js +22 -67
  21. package/lib/addresses/marketAddresses.d.ts +4 -0
  22. package/lib/addresses/marketAddresses.js +15 -0
  23. package/lib/addresses/pda.d.ts +12 -0
  24. package/lib/addresses/pda.js +83 -0
  25. package/lib/admin.d.ts +12 -18
  26. package/lib/admin.js +398 -558
  27. package/lib/clearingHouse.d.ts +83 -109
  28. package/lib/clearingHouse.js +832 -893
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -22
  32. package/lib/clearingHouseUser.js +155 -141
  33. package/lib/clearingHouseUserConfig.d.ts +14 -0
  34. package/lib/clearingHouseUserConfig.js +2 -0
  35. package/lib/config.d.ts +12 -0
  36. package/lib/config.js +35 -4
  37. package/lib/constants/banks.d.ts +16 -0
  38. package/lib/constants/banks.js +41 -0
  39. package/lib/constants/markets.d.ts +8 -3
  40. package/lib/constants/markets.js +13 -206
  41. package/lib/constants/numericConstants.d.ts +17 -0
  42. package/lib/constants/numericConstants.js +23 -6
  43. package/lib/events/eventList.d.ts +22 -0
  44. package/lib/events/eventList.js +77 -0
  45. package/lib/events/eventSubscriber.d.ts +34 -0
  46. package/lib/events/eventSubscriber.js +126 -0
  47. package/lib/events/fetchLogs.d.ts +13 -0
  48. package/lib/events/fetchLogs.js +39 -0
  49. package/lib/events/pollingLogProvider.d.ts +15 -0
  50. package/lib/events/pollingLogProvider.js +53 -0
  51. package/lib/events/sort.d.ts +2 -0
  52. package/lib/events/sort.js +44 -0
  53. package/lib/events/txEventCache.d.ts +24 -0
  54. package/lib/events/txEventCache.js +71 -0
  55. package/lib/events/types.d.ts +49 -0
  56. package/lib/events/types.js +20 -0
  57. package/lib/events/webSocketLogProvider.d.ts +12 -0
  58. package/lib/events/webSocketLogProvider.js +30 -0
  59. package/lib/examples/makeTradeExample.js +26 -27
  60. package/lib/factory/bigNum.d.ts +118 -0
  61. package/lib/factory/bigNum.js +364 -0
  62. package/lib/factory/oracleClient.d.ts +1 -2
  63. package/lib/factory/oracleClient.js +6 -2
  64. package/lib/idl/clearing_house.json +2258 -2774
  65. package/lib/index.d.ts +14 -5
  66. package/lib/index.js +18 -5
  67. package/lib/math/amm.d.ts +24 -29
  68. package/lib/math/amm.js +209 -176
  69. package/lib/math/auction.d.ts +5 -0
  70. package/lib/math/auction.js +42 -0
  71. package/lib/math/bankBalance.d.ts +9 -0
  72. package/lib/math/bankBalance.js +75 -0
  73. package/lib/math/conversion.d.ts +0 -1
  74. package/lib/math/conversion.js +1 -5
  75. package/lib/math/funding.d.ts +6 -6
  76. package/lib/math/funding.js +158 -175
  77. package/lib/math/market.d.ts +6 -6
  78. package/lib/math/market.js +10 -9
  79. package/lib/math/orders.d.ts +6 -1
  80. package/lib/math/orders.js +38 -1
  81. package/lib/math/position.d.ts +7 -5
  82. package/lib/math/position.js +29 -27
  83. package/lib/math/repeg.d.ts +22 -0
  84. package/lib/math/repeg.js +128 -0
  85. package/lib/math/trade.d.ts +5 -4
  86. package/lib/math/trade.js +29 -24
  87. package/lib/mockUSDCFaucet.js +87 -116
  88. package/lib/oracles/oracleClientCache.d.ts +8 -0
  89. package/lib/oracles/oracleClientCache.js +19 -0
  90. package/lib/oracles/pythClient.d.ts +3 -5
  91. package/lib/oracles/pythClient.js +12 -31
  92. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  93. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  94. package/lib/oracles/switchboardClient.d.ts +3 -5
  95. package/lib/oracles/switchboardClient.js +29 -50
  96. package/lib/oracles/types.d.ts +6 -1
  97. package/lib/orderParams.d.ts +14 -5
  98. package/lib/orderParams.js +8 -96
  99. package/lib/orders.d.ts +6 -7
  100. package/lib/orders.js +11 -89
  101. package/lib/slot/SlotSubscriber.d.ts +19 -0
  102. package/lib/slot/SlotSubscriber.js +26 -0
  103. package/lib/tx/retryTxSender.d.ts +2 -2
  104. package/lib/tx/retryTxSender.js +108 -123
  105. package/lib/tx/types.d.ts +5 -1
  106. package/lib/tx/utils.d.ts +1 -1
  107. package/lib/tx/utils.js +11 -2
  108. package/lib/types.d.ts +180 -110
  109. package/lib/types.js +54 -1
  110. package/lib/userName.d.ts +4 -0
  111. package/lib/userName.js +20 -0
  112. package/lib/util/computeUnits.js +10 -21
  113. package/lib/util/tps.js +11 -22
  114. package/lib/wallet.js +7 -20
  115. package/package.json +11 -4
  116. package/src/accounts/bulkAccountLoader.js +197 -0
  117. package/src/accounts/bulkAccountLoader.ts +21 -15
  118. package/src/accounts/bulkUserSubscription.js +33 -0
  119. package/src/accounts/bulkUserSubscription.ts +1 -45
  120. package/src/accounts/fetch.js +29 -0
  121. package/src/accounts/fetch.ts +33 -0
  122. package/src/accounts/pollingClearingHouseAccountSubscriber.js +311 -0
  123. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  124. package/src/accounts/pollingOracleSubscriber.js +93 -0
  125. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  126. package/src/accounts/pollingTokenAccountSubscriber.js +90 -0
  127. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  128. package/src/accounts/pollingUserAccountSubscriber.js +132 -0
  129. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  130. package/src/accounts/types.js +10 -0
  131. package/src/accounts/types.ts +41 -70
  132. package/src/accounts/utils.js +7 -0
  133. package/src/accounts/webSocketAccountSubscriber.js +93 -0
  134. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  135. package/src/accounts/webSocketClearingHouseAccountSubscriber.js +233 -0
  136. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  137. package/src/accounts/webSocketUserAccountSubscriber.js +62 -0
  138. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  139. package/src/addresses/marketAddresses.js +26 -0
  140. package/src/addresses/marketAddresses.ts +18 -0
  141. package/{lib/addresses.js → src/addresses/pda.js} +45 -34
  142. package/src/addresses/pda.ts +118 -0
  143. package/src/admin.ts +247 -336
  144. package/src/assert/assert.js +9 -0
  145. package/src/clearingHouse.ts +1023 -1026
  146. package/src/clearingHouseConfig.ts +37 -0
  147. package/src/clearingHouseUser.ts +275 -185
  148. package/src/clearingHouseUserConfig.ts +18 -0
  149. package/src/config.ts +54 -1
  150. package/src/constants/banks.ts +50 -0
  151. package/src/constants/markets.ts +16 -207
  152. package/src/constants/numericConstants.ts +34 -5
  153. package/src/events/eventList.js +77 -0
  154. package/src/events/eventList.ts +94 -0
  155. package/src/events/eventSubscriber.js +139 -0
  156. package/src/events/eventSubscriber.ts +194 -0
  157. package/src/events/fetchLogs.js +50 -0
  158. package/src/events/fetchLogs.ts +80 -0
  159. package/src/events/pollingLogProvider.js +64 -0
  160. package/src/events/pollingLogProvider.ts +79 -0
  161. package/src/events/sort.js +44 -0
  162. package/src/events/sort.ts +65 -0
  163. package/src/events/txEventCache.js +71 -0
  164. package/src/events/txEventCache.ts +74 -0
  165. package/src/events/types.js +20 -0
  166. package/src/events/types.ts +98 -0
  167. package/src/events/webSocketLogProvider.js +41 -0
  168. package/src/events/webSocketLogProvider.ts +38 -0
  169. package/src/examples/makeTradeExample.js +80 -0
  170. package/src/examples/makeTradeExample.ts +20 -11
  171. package/src/factory/bigNum.js +364 -0
  172. package/src/factory/bigNum.ts +524 -0
  173. package/src/factory/oracleClient.js +20 -0
  174. package/src/factory/oracleClient.ts +7 -4
  175. package/src/idl/clearing_house.json +2258 -2774
  176. package/src/index.js +69 -0
  177. package/src/index.ts +14 -5
  178. package/src/math/amm.js +369 -0
  179. package/src/math/amm.ts +382 -243
  180. package/src/math/auction.js +42 -0
  181. package/src/math/auction.ts +43 -0
  182. package/src/math/bankBalance.js +75 -0
  183. package/src/math/bankBalance.ts +112 -0
  184. package/src/math/conversion.js +11 -0
  185. package/src/math/conversion.ts +1 -11
  186. package/src/math/funding.js +248 -0
  187. package/src/math/funding.ts +12 -9
  188. package/src/math/market.js +57 -0
  189. package/src/math/market.ts +37 -30
  190. package/src/math/oracles.js +26 -0
  191. package/src/math/orders.js +110 -0
  192. package/src/math/orders.ts +43 -1
  193. package/src/math/position.js +140 -0
  194. package/src/math/position.ts +52 -35
  195. package/src/math/repeg.js +128 -0
  196. package/src/math/repeg.ts +176 -0
  197. package/src/math/state.js +15 -0
  198. package/src/math/trade.js +253 -0
  199. package/src/math/trade.ts +55 -47
  200. package/src/math/utils.js +26 -0
  201. package/src/math/utils.js.map +1 -0
  202. package/src/mockUSDCFaucet.js +171 -0
  203. package/src/oracles/oracleClientCache.js +19 -0
  204. package/src/oracles/oracleClientCache.ts +20 -0
  205. package/src/oracles/pythClient.js +46 -0
  206. package/src/oracles/pythClient.ts +4 -11
  207. package/src/oracles/quoteAssetOracleClient.js +32 -0
  208. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  209. package/src/oracles/switchboardClient.js +69 -0
  210. package/src/oracles/switchboardClient.ts +11 -24
  211. package/src/oracles/types.js +2 -0
  212. package/src/oracles/types.ts +7 -1
  213. package/src/orderParams.js +20 -0
  214. package/src/orderParams.ts +20 -141
  215. package/src/orders.js +134 -0
  216. package/src/orders.ts +25 -134
  217. package/src/slot/SlotSubscriber.js +39 -0
  218. package/src/slot/SlotSubscriber.ts +42 -0
  219. package/src/token/index.js +38 -0
  220. package/src/tx/retryTxSender.js +188 -0
  221. package/src/tx/retryTxSender.ts +6 -4
  222. package/src/tx/types.js +2 -0
  223. package/src/tx/types.ts +6 -1
  224. package/src/tx/utils.js +17 -0
  225. package/src/tx/utils.ts +22 -3
  226. package/src/types.js +114 -0
  227. package/src/types.ts +176 -124
  228. package/src/userName.js +20 -0
  229. package/src/userName.ts +20 -0
  230. package/src/util/promiseTimeout.js +14 -0
  231. package/src/util/tps.js +27 -0
  232. package/src/wallet.js +35 -0
  233. package/tests/bn/test.ts +255 -0
  234. package/tsconfig.json +12 -12
  235. package/lib/addresses.d.ts +0 -10
  236. package/lib/constants/accounts.d.ts +0 -15
  237. package/lib/constants/accounts.js +0 -18
  238. package/lib/factory/clearingHouse.d.ts +0 -35
  239. package/lib/factory/clearingHouse.js +0 -81
  240. package/lib/factory/clearingHouseUser.d.ts +0 -19
  241. package/lib/factory/clearingHouseUser.js +0 -34
  242. package/lib/math/insuranceFund.d.ts +0 -15
  243. package/lib/math/insuranceFund.js +0 -33
  244. package/lib/settlement.d.ts +0 -4
  245. package/lib/settlement.js +0 -10
  246. package/lib/tx/defaultTxSender.d.ts +0 -8
  247. package/lib/tx/defaultTxSender.js +0 -12
  248. package/src/addresses.ts +0 -82
  249. package/src/constants/accounts.ts +0 -26
  250. package/src/factory/clearingHouse.ts +0 -173
  251. package/src/factory/clearingHouseUser.ts +0 -73
  252. package/src/math/insuranceFund.ts +0 -29
  253. package/src/settlement.ts +0 -9
  254. package/src/tx/defaultTxSender.ts +0 -24
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.36-master.7",
3
+ "version": "0.2.0-master.10",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -13,6 +13,7 @@
13
13
  "lint": "eslint './**/*.{ts,tsx}' --quiet",
14
14
  "build": "yarn clean && tsc",
15
15
  "clean": "rm -rf lib",
16
+ "test": "mocha -r ts-node/register tests/**/*.ts",
16
17
  "patch-and-pub": "npm version patch --force && npm publish"
17
18
  },
18
19
  "keywords": [
@@ -29,19 +30,25 @@
29
30
  },
30
31
  "dependencies": {
31
32
  "@project-serum/anchor": "0.24.2",
32
- "@pythnetwork/client": "^2.5.1",
33
+ "@pythnetwork/client": "2.5.3",
33
34
  "@solana/spl-token": "^0.1.6",
34
- "@solana/web3.js": "^1.22.0",
35
+ "@solana/web3.js": "1.41.0",
35
36
  "@switchboard-xyz/switchboard-v2": "^0.0.67",
36
37
  "strict-event-emitter-types": "^2.0.0",
37
38
  "uuid": "^8.3.2"
38
39
  },
39
40
  "devDependencies": {
41
+ "@types/chai": "^4.3.1",
42
+ "@types/jest": "^28.1.3",
43
+ "@types/mocha": "^9.1.1",
40
44
  "@typescript-eslint/eslint-plugin": "^4.28.0",
41
45
  "@typescript-eslint/parser": "^4.28.0",
46
+ "chai": "^4.3.6",
42
47
  "eslint": "^7.29.0",
43
48
  "eslint-config-prettier": "^8.3.0",
44
- "eslint-plugin-prettier": "^3.4.0"
49
+ "eslint-plugin-prettier": "^3.4.0",
50
+ "mocha": "^10.0.0",
51
+ "ts-node": "^10.8.0"
45
52
  },
46
53
  "description": "SDK for Drift Protocol v1",
47
54
  "engines": {
@@ -0,0 +1,197 @@
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 });
12
+ exports.BulkAccountLoader = void 0;
13
+ const uuid_1 = require("uuid");
14
+ const promiseTimeout_1 = require("../util/promiseTimeout");
15
+ const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
16
+ const oneMinute = 60 * 1000;
17
+ class BulkAccountLoader {
18
+ constructor(connection, commitment, pollingFrequency) {
19
+ this.accountsToLoad = new Map();
20
+ this.bufferAndSlotMap = new Map();
21
+ this.errorCallbacks = new Map();
22
+ this.lastTimeLoadingPromiseCleared = Date.now();
23
+ this.mostRecentSlot = 0;
24
+ this.connection = connection;
25
+ this.commitment = commitment;
26
+ this.pollingFrequency = pollingFrequency;
27
+ }
28
+ addAccount(publicKey, callback) {
29
+ const existingSize = this.accountsToLoad.size;
30
+ const callbackId = uuid_1.v4();
31
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
32
+ if (existingAccountToLoad) {
33
+ existingAccountToLoad.callbacks.set(callbackId, callback);
34
+ }
35
+ else {
36
+ const callbacks = new Map();
37
+ callbacks.set(callbackId, callback);
38
+ const newAccountToLoad = {
39
+ publicKey,
40
+ callbacks,
41
+ };
42
+ this.accountsToLoad.set(publicKey.toString(), newAccountToLoad);
43
+ }
44
+ if (existingSize === 0) {
45
+ this.startPolling();
46
+ }
47
+ // if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
48
+ this.loadPromise = undefined;
49
+ return callbackId;
50
+ }
51
+ removeAccount(publicKey, callbackId) {
52
+ const existingAccountToLoad = this.accountsToLoad.get(publicKey.toString());
53
+ if (existingAccountToLoad) {
54
+ existingAccountToLoad.callbacks.delete(callbackId);
55
+ if (existingAccountToLoad.callbacks.size === 0) {
56
+ this.accountsToLoad.delete(existingAccountToLoad.publicKey.toString());
57
+ }
58
+ }
59
+ if (this.accountsToLoad.size === 0) {
60
+ this.stopPolling();
61
+ }
62
+ }
63
+ addErrorCallbacks(callback) {
64
+ const callbackId = uuid_1.v4();
65
+ this.errorCallbacks.set(callbackId, callback);
66
+ return callbackId;
67
+ }
68
+ removeErrorCallbacks(callbackId) {
69
+ this.errorCallbacks.delete(callbackId);
70
+ }
71
+ chunks(array, size) {
72
+ return new Array(Math.ceil(array.length / size))
73
+ .fill(null)
74
+ .map((_, index) => index * size)
75
+ .map((begin) => array.slice(begin, begin + size));
76
+ }
77
+ load() {
78
+ return __awaiter(this, void 0, void 0, function* () {
79
+ if (this.loadPromise) {
80
+ const now = Date.now();
81
+ if (now - this.lastTimeLoadingPromiseCleared > oneMinute) {
82
+ this.loadPromise = undefined;
83
+ }
84
+ else {
85
+ return this.loadPromise;
86
+ }
87
+ }
88
+ this.loadPromise = new Promise((resolver) => {
89
+ this.loadPromiseResolver = resolver;
90
+ });
91
+ this.lastTimeLoadingPromiseCleared = Date.now();
92
+ try {
93
+ const chunks = this.chunks(Array.from(this.accountsToLoad.values()), GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE);
94
+ yield Promise.all(chunks.map((chunk) => {
95
+ return this.loadChunk(chunk);
96
+ }));
97
+ }
98
+ catch (e) {
99
+ console.error(`Error in bulkAccountLoader.load()`);
100
+ console.error(e);
101
+ for (const [_, callback] of this.errorCallbacks) {
102
+ callback(e);
103
+ }
104
+ }
105
+ finally {
106
+ this.loadPromiseResolver();
107
+ this.loadPromise = undefined;
108
+ }
109
+ });
110
+ }
111
+ loadChunk(accountsToLoad) {
112
+ return __awaiter(this, void 0, void 0, function* () {
113
+ if (accountsToLoad.length === 0) {
114
+ return;
115
+ }
116
+ const args = [
117
+ accountsToLoad.map((accountToLoad) => {
118
+ return accountToLoad.publicKey.toBase58();
119
+ }),
120
+ { commitment: this.commitment },
121
+ ];
122
+ const rpcResponse = yield promiseTimeout_1.promiseTimeout(
123
+ // @ts-ignore
124
+ this.connection._rpcRequest('getMultipleAccounts', args), 10 * 1000 // 30 second timeout
125
+ );
126
+ if (rpcResponse === null) {
127
+ this.log('request to rpc timed out');
128
+ return;
129
+ }
130
+ const newSlot = rpcResponse.result.context.slot;
131
+ if (newSlot > this.mostRecentSlot) {
132
+ this.mostRecentSlot = newSlot;
133
+ }
134
+ for (const i in accountsToLoad) {
135
+ const accountToLoad = accountsToLoad[i];
136
+ const key = accountToLoad.publicKey.toString();
137
+ const oldRPCResponse = this.bufferAndSlotMap.get(key);
138
+ let newBuffer = undefined;
139
+ if (rpcResponse.result.value[i]) {
140
+ const raw = rpcResponse.result.value[i].data[0];
141
+ const dataType = rpcResponse.result.value[i].data[1];
142
+ newBuffer = Buffer.from(raw, dataType);
143
+ }
144
+ if (!oldRPCResponse) {
145
+ this.bufferAndSlotMap.set(key, {
146
+ slot: newSlot,
147
+ buffer: newBuffer,
148
+ });
149
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
150
+ continue;
151
+ }
152
+ if (newSlot <= oldRPCResponse.slot) {
153
+ continue;
154
+ }
155
+ const oldBuffer = oldRPCResponse.buffer;
156
+ if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
157
+ this.bufferAndSlotMap.set(key, {
158
+ slot: newSlot,
159
+ buffer: newBuffer,
160
+ });
161
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
162
+ }
163
+ }
164
+ });
165
+ }
166
+ handleAccountCallbacks(accountToLoad, buffer, slot) {
167
+ for (const [_, callback] of accountToLoad.callbacks) {
168
+ callback(buffer, slot);
169
+ }
170
+ }
171
+ getBufferAndSlot(publicKey) {
172
+ return this.bufferAndSlotMap.get(publicKey.toString());
173
+ }
174
+ startPolling() {
175
+ if (this.intervalId) {
176
+ return;
177
+ }
178
+ this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
179
+ }
180
+ stopPolling() {
181
+ if (this.intervalId) {
182
+ clearInterval(this.intervalId);
183
+ this.intervalId = undefined;
184
+ }
185
+ }
186
+ log(msg) {
187
+ console.log(msg);
188
+ }
189
+ updatePollingFrequency(pollingFrequency) {
190
+ this.stopPolling();
191
+ this.pollingFrequency = pollingFrequency;
192
+ if (this.accountsToLoad.size > 0) {
193
+ this.startPolling();
194
+ }
195
+ }
196
+ }
197
+ exports.BulkAccountLoader = BulkAccountLoader;
@@ -1,11 +1,11 @@
1
1
  import { Commitment, Connection, PublicKey } from '@solana/web3.js';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
- import { AccountData } from './types';
3
+ import { BufferAndSlot } from './types';
4
4
  import { promiseTimeout } from '../util/promiseTimeout';
5
5
 
6
6
  type AccountToLoad = {
7
7
  publicKey: PublicKey;
8
- callbacks: Map<string, (buffer: Buffer) => void>;
8
+ callbacks: Map<string, (buffer: Buffer, slot: number) => void>;
9
9
  };
10
10
 
11
11
  const GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE = 99;
@@ -17,7 +17,7 @@ export class BulkAccountLoader {
17
17
  commitment: Commitment;
18
18
  pollingFrequency: number;
19
19
  accountsToLoad = new Map<string, AccountToLoad>();
20
- accountData = new Map<string, AccountData>();
20
+ bufferAndSlotMap = new Map<string, BufferAndSlot>();
21
21
  errorCallbacks = new Map<string, (e) => void>();
22
22
  intervalId?: NodeJS.Timer;
23
23
  // to handle clients spamming load
@@ -38,7 +38,7 @@ export class BulkAccountLoader {
38
38
 
39
39
  public addAccount(
40
40
  publicKey: PublicKey,
41
- callback: (buffer: Buffer) => void
41
+ callback: (buffer: Buffer, slot: number) => void
42
42
  ): string {
43
43
  const existingSize = this.accountsToLoad.size;
44
44
 
@@ -47,7 +47,10 @@ export class BulkAccountLoader {
47
47
  if (existingAccountToLoad) {
48
48
  existingAccountToLoad.callbacks.set(callbackId, callback);
49
49
  } else {
50
- const callbacks = new Map<string, (buffer: Buffer) => void>();
50
+ const callbacks = new Map<
51
+ string,
52
+ (buffer: Buffer, slot: number) => void
53
+ >();
51
54
  callbacks.set(callbackId, callback);
52
55
  const newAccountToLoad = {
53
56
  publicKey,
@@ -167,7 +170,7 @@ export class BulkAccountLoader {
167
170
  for (const i in accountsToLoad) {
168
171
  const accountToLoad = accountsToLoad[i];
169
172
  const key = accountToLoad.publicKey.toString();
170
- const oldRPCResponse = this.accountData.get(key);
173
+ const oldRPCResponse = this.bufferAndSlotMap.get(key);
171
174
 
172
175
  let newBuffer: Buffer | undefined = undefined;
173
176
  if (rpcResponse.result.value[i]) {
@@ -177,11 +180,11 @@ export class BulkAccountLoader {
177
180
  }
178
181
 
179
182
  if (!oldRPCResponse) {
180
- this.accountData.set(key, {
183
+ this.bufferAndSlotMap.set(key, {
181
184
  slot: newSlot,
182
185
  buffer: newBuffer,
183
186
  });
184
- this.handleAccountCallbacks(accountToLoad, newBuffer);
187
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
185
188
  continue;
186
189
  }
187
190
 
@@ -191,24 +194,27 @@ export class BulkAccountLoader {
191
194
 
192
195
  const oldBuffer = oldRPCResponse.buffer;
193
196
  if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
194
- this.accountData.set(key, {
197
+ this.bufferAndSlotMap.set(key, {
195
198
  slot: newSlot,
196
199
  buffer: newBuffer,
197
200
  });
198
- this.handleAccountCallbacks(accountToLoad, newBuffer);
201
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
199
202
  }
200
203
  }
201
204
  }
202
205
 
203
- handleAccountCallbacks(accountToLoad: AccountToLoad, buffer: Buffer): void {
206
+ handleAccountCallbacks(
207
+ accountToLoad: AccountToLoad,
208
+ buffer: Buffer,
209
+ slot: number
210
+ ): void {
204
211
  for (const [_, callback] of accountToLoad.callbacks) {
205
- callback(buffer);
212
+ callback(buffer, slot);
206
213
  }
207
214
  }
208
215
 
209
- public getAccountData(publicKey: PublicKey): Buffer | undefined {
210
- const accountData = this.accountData.get(publicKey.toString());
211
- return accountData?.buffer;
216
+ public getBufferAndSlot(publicKey: PublicKey): BufferAndSlot | undefined {
217
+ return this.bufferAndSlotMap.get(publicKey.toString());
212
218
  }
213
219
 
214
220
  public startPolling(): void {
@@ -0,0 +1,33 @@
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 });
12
+ exports.bulkPollingUserSubscribe = void 0;
13
+ /**
14
+ * @param users
15
+ * @param accountLoader
16
+ */
17
+ function bulkPollingUserSubscribe(users, accountLoader) {
18
+ return __awaiter(this, void 0, void 0, function* () {
19
+ if (users.length === 0) {
20
+ yield accountLoader.load();
21
+ return;
22
+ }
23
+ yield Promise.all(users.map((user) => {
24
+ // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
25
+ return user.accountSubscriber.addToAccountLoader();
26
+ }));
27
+ yield accountLoader.load();
28
+ yield Promise.all(users.map((user) => __awaiter(this, void 0, void 0, function* () {
29
+ return user.subscribe();
30
+ })));
31
+ });
32
+ }
33
+ exports.bulkPollingUserSubscribe = bulkPollingUserSubscribe;
@@ -1,9 +1,6 @@
1
1
  import { ClearingHouseUser } from '../clearingHouseUser';
2
2
  import { BulkAccountLoader } from './bulkAccountLoader';
3
3
  import { PollingUserAccountSubscriber } from './pollingUserAccountSubscriber';
4
- import { UserAccount, UserOrdersAccount } from '../types';
5
- import { UserPublicKeys } from './types';
6
- import { ProgramAccount } from '@project-serum/anchor';
7
4
 
8
5
  /**
9
6
  * @param users
@@ -18,53 +15,12 @@ export async function bulkPollingUserSubscribe(
18
15
  return;
19
16
  }
20
17
 
21
- // Fetch all the accounts first
22
- const program = users[0].clearingHouse.program;
23
- let userProgramAccounts: ProgramAccount[];
24
- let orderProgramAccounts: ProgramAccount[];
25
- await Promise.all([
26
- (async () => {
27
- userProgramAccounts = await program.account.user.all();
28
- })(),
29
- (async () => {
30
- orderProgramAccounts = await program.account.userOrders.all();
31
- })(),
32
- ]);
33
-
34
- // Create a map of the authority to keys
35
- const authorityToKeys = new Map<string, UserPublicKeys>();
36
- const userToAuthority = new Map<string, string>();
37
- for (const userProgramAccount of userProgramAccounts) {
38
- const userAccountPublicKey = userProgramAccount.publicKey;
39
- const userAccount = userProgramAccount.account as UserAccount;
40
-
41
- authorityToKeys.set(userAccount.authority.toString(), {
42
- user: userAccountPublicKey,
43
- userPositions: userAccount.positions,
44
- userOrders: undefined,
45
- });
46
-
47
- userToAuthority.set(
48
- userAccountPublicKey.toString(),
49
- userAccount.authority.toString()
50
- );
51
- }
52
- for (const orderProgramAccount of orderProgramAccounts) {
53
- const userOrderAccountPublicKey = orderProgramAccount.publicKey;
54
- const userOrderAccount = orderProgramAccount.account as UserOrdersAccount;
55
-
56
- const authority = userToAuthority.get(userOrderAccount.user.toString());
57
- const userPublicKeys = authorityToKeys.get(authority);
58
- userPublicKeys.userOrders = userOrderAccountPublicKey;
59
- }
60
-
61
18
  await Promise.all(
62
19
  users.map((user) => {
63
20
  // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
64
- const userPublicKeys = authorityToKeys.get(user.authority.toString());
65
21
  return (
66
22
  user.accountSubscriber as PollingUserAccountSubscriber
67
- ).addToAccountLoader(userPublicKeys);
23
+ ).addToAccountLoader();
68
24
  })
69
25
  );
70
26
 
@@ -0,0 +1,29 @@
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 });
12
+ exports.fetchUserAccounts = void 0;
13
+ const pda_1 = require("../addresses/pda");
14
+ function fetchUserAccounts(connection, program, authority, limit = 8) {
15
+ return __awaiter(this, void 0, void 0, function* () {
16
+ const userAccountPublicKeys = new Array();
17
+ for (let i = 0; i < limit; i++) {
18
+ userAccountPublicKeys.push(yield pda_1.getUserAccountPublicKey(program.programId, authority, i));
19
+ }
20
+ const accountInfos = yield connection.getMultipleAccountsInfo(userAccountPublicKeys, 'confirmed');
21
+ return accountInfos.map((accountInfo) => {
22
+ if (!accountInfo) {
23
+ return undefined;
24
+ }
25
+ return program.account.user.coder.accounts.decode('User', accountInfo.data);
26
+ });
27
+ });
28
+ }
29
+ exports.fetchUserAccounts = fetchUserAccounts;
@@ -0,0 +1,33 @@
1
+ import { Connection, PublicKey } from '@solana/web3.js';
2
+ import { UserAccount } from '../types';
3
+ import { getUserAccountPublicKey } from '../addresses/pda';
4
+ import { Program } from '@project-serum/anchor';
5
+
6
+ export async function fetchUserAccounts(
7
+ connection: Connection,
8
+ program: Program,
9
+ authority: PublicKey,
10
+ limit = 8
11
+ ): Promise<(UserAccount | undefined)[]> {
12
+ const userAccountPublicKeys = new Array<PublicKey>();
13
+ for (let i = 0; i < limit; i++) {
14
+ userAccountPublicKeys.push(
15
+ await getUserAccountPublicKey(program.programId, authority, i)
16
+ );
17
+ }
18
+
19
+ const accountInfos = await connection.getMultipleAccountsInfo(
20
+ userAccountPublicKeys,
21
+ 'confirmed'
22
+ );
23
+
24
+ return accountInfos.map((accountInfo) => {
25
+ if (!accountInfo) {
26
+ return undefined;
27
+ }
28
+ return program.account.user.coder.accounts.decode(
29
+ 'User',
30
+ accountInfo.data
31
+ ) as UserAccount;
32
+ });
33
+ }