@drift-labs/sdk 0.1.36-master.5 → 0.2.0-master.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 (197) hide show
  1. package/lib/accounts/bulkAccountLoader.d.ts +7 -6
  2. package/lib/accounts/bulkAccountLoader.js +83 -93
  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 +8 -12
  26. package/lib/admin.js +366 -490
  27. package/lib/clearingHouse.d.ts +84 -103
  28. package/lib/clearingHouse.js +779 -810
  29. package/lib/clearingHouseConfig.d.ts +34 -0
  30. package/lib/clearingHouseConfig.js +2 -0
  31. package/lib/clearingHouseUser.d.ts +19 -18
  32. package/lib/clearingHouseUser.js +157 -115
  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 +34 -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 +16 -0
  42. package/lib/constants/numericConstants.js +22 -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 +112 -0
  61. package/lib/factory/bigNum.js +356 -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 +1739 -2287
  65. package/lib/index.d.ts +13 -4
  66. package/lib/index.js +13 -4
  67. package/lib/math/amm.d.ts +19 -29
  68. package/lib/math/amm.js +129 -179
  69. package/lib/math/auction.d.ts +5 -0
  70. package/lib/math/auction.js +39 -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/oracles.d.ts +3 -0
  80. package/lib/math/oracles.js +26 -0
  81. package/lib/math/orders.d.ts +5 -0
  82. package/lib/math/orders.js +31 -1
  83. package/lib/math/position.d.ts +7 -4
  84. package/lib/math/position.js +27 -9
  85. package/lib/math/repeg.d.ts +22 -0
  86. package/lib/math/repeg.js +128 -0
  87. package/lib/math/trade.d.ts +13 -8
  88. package/lib/math/trade.js +85 -22
  89. package/lib/mockUSDCFaucet.js +87 -116
  90. package/lib/oracles/oracleClientCache.d.ts +8 -0
  91. package/lib/oracles/oracleClientCache.js +19 -0
  92. package/lib/oracles/pythClient.d.ts +3 -5
  93. package/lib/oracles/pythClient.js +12 -30
  94. package/lib/oracles/quoteAssetOracleClient.d.ts +9 -0
  95. package/lib/oracles/quoteAssetOracleClient.js +21 -0
  96. package/lib/oracles/switchboardClient.d.ts +3 -5
  97. package/lib/oracles/switchboardClient.js +29 -47
  98. package/lib/oracles/types.d.ts +7 -1
  99. package/lib/orders.d.ts +6 -6
  100. package/lib/orders.js +10 -9
  101. package/lib/slot/SlotSubscriber.d.ts +12 -0
  102. package/lib/slot/SlotSubscriber.js +23 -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 +105 -98
  109. package/lib/types.js +13 -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 +10 -3
  116. package/src/accounts/bulkAccountLoader.ts +26 -15
  117. package/src/accounts/bulkUserSubscription.ts +1 -45
  118. package/src/accounts/fetch.ts +33 -0
  119. package/src/accounts/pollingClearingHouseAccountSubscriber.ts +249 -214
  120. package/src/accounts/pollingOracleSubscriber.ts +16 -8
  121. package/src/accounts/pollingTokenAccountSubscriber.ts +11 -8
  122. package/src/accounts/pollingUserAccountSubscriber.ts +21 -86
  123. package/src/accounts/types.ts +41 -70
  124. package/src/accounts/webSocketAccountSubscriber.ts +33 -16
  125. package/src/accounts/webSocketClearingHouseAccountSubscriber.ts +190 -240
  126. package/src/accounts/webSocketUserAccountSubscriber.ts +11 -71
  127. package/src/addresses/marketAddresses.ts +18 -0
  128. package/src/addresses/pda.ts +118 -0
  129. package/src/admin.ts +209 -267
  130. package/src/clearingHouse.ts +921 -829
  131. package/src/clearingHouseConfig.ts +37 -0
  132. package/src/clearingHouseUser.ts +280 -127
  133. package/src/clearingHouseUserConfig.ts +18 -0
  134. package/src/config.ts +54 -1
  135. package/src/constants/banks.ts +43 -0
  136. package/src/constants/markets.ts +16 -207
  137. package/src/constants/numericConstants.ts +33 -5
  138. package/src/events/eventList.ts +94 -0
  139. package/src/events/eventSubscriber.ts +194 -0
  140. package/src/events/fetchLogs.ts +80 -0
  141. package/src/events/pollingLogProvider.ts +79 -0
  142. package/src/events/sort.ts +65 -0
  143. package/src/events/txEventCache.ts +74 -0
  144. package/src/events/types.ts +98 -0
  145. package/src/events/webSocketLogProvider.ts +38 -0
  146. package/src/examples/makeTradeExample.ts +20 -11
  147. package/src/factory/bigNum.ts +507 -0
  148. package/src/factory/oracleClient.ts +7 -4
  149. package/src/idl/clearing_house.json +1739 -2287
  150. package/src/index.ts +13 -4
  151. package/src/math/amm.ts +229 -245
  152. package/src/math/auction.ts +39 -0
  153. package/src/math/bankBalance.ts +112 -0
  154. package/src/math/conversion.ts +1 -11
  155. package/src/math/funding.ts +12 -9
  156. package/src/math/market.ts +37 -30
  157. package/src/math/oracles.ts +36 -0
  158. package/src/math/orders.ts +38 -0
  159. package/src/math/position.ts +48 -13
  160. package/src/math/repeg.ts +175 -0
  161. package/src/math/trade.ts +114 -36
  162. package/src/math/utils.js +27 -0
  163. package/src/math/utils.js.map +1 -0
  164. package/src/oracles/oracleClientCache.ts +20 -0
  165. package/src/oracles/pythClient.ts +5 -11
  166. package/src/oracles/quoteAssetOracleClient.ts +25 -0
  167. package/src/oracles/switchboardClient.ts +16 -24
  168. package/src/oracles/types.ts +8 -1
  169. package/src/orders.ts +35 -20
  170. package/src/slot/SlotSubscriber.ts +32 -0
  171. package/src/tx/retryTxSender.ts +6 -4
  172. package/src/tx/types.ts +6 -1
  173. package/src/tx/utils.ts +22 -3
  174. package/src/types.ts +108 -110
  175. package/src/userName.ts +20 -0
  176. package/src/util/computeUnits.js +17 -0
  177. package/src/util/computeUnits.js.map +1 -0
  178. package/tests/bn/test.ts +255 -0
  179. package/tsconfig.json +12 -12
  180. package/lib/addresses.d.ts +0 -9
  181. package/lib/addresses.js +0 -87
  182. package/lib/constants/accounts.d.ts +0 -15
  183. package/lib/constants/accounts.js +0 -18
  184. package/lib/factory/clearingHouse.d.ts +0 -35
  185. package/lib/factory/clearingHouse.js +0 -81
  186. package/lib/factory/clearingHouseUser.d.ts +0 -19
  187. package/lib/factory/clearingHouseUser.js +0 -34
  188. package/lib/math/insuranceFund.d.ts +0 -15
  189. package/lib/math/insuranceFund.js +0 -33
  190. package/lib/tx/defaultTxSender.d.ts +0 -8
  191. package/lib/tx/defaultTxSender.js +0 -12
  192. package/src/addresses.ts +0 -71
  193. package/src/constants/accounts.ts +0 -26
  194. package/src/factory/clearingHouse.ts +0 -173
  195. package/src/factory/clearingHouseUser.ts +0 -73
  196. package/src/math/insuranceFund.ts +0 -29
  197. package/src/tx/defaultTxSender.ts +0 -24
package/lib/types.js CHANGED
@@ -1,12 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TradeSide = exports.isVariant = exports.OrderTriggerCondition = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.PositionDirection = exports.SwapDirection = void 0;
3
+ exports.TradeSide = exports.isOneOfVariant = exports.isVariant = exports.OrderTriggerCondition = exports.OrderAction = exports.OrderDiscountTier = exports.OrderStatus = exports.OrderType = exports.OracleSource = exports.PositionDirection = exports.BankBalanceType = exports.SwapDirection = void 0;
4
4
  // # Utility Types / Enums / Constants
5
5
  class SwapDirection {
6
6
  }
7
7
  exports.SwapDirection = SwapDirection;
8
8
  SwapDirection.ADD = { add: {} };
9
9
  SwapDirection.REMOVE = { remove: {} };
10
+ class BankBalanceType {
11
+ }
12
+ exports.BankBalanceType = BankBalanceType;
13
+ BankBalanceType.DEPOSIT = { deposit: {} };
14
+ BankBalanceType.BORROW = { borrow: {} };
10
15
  class PositionDirection {
11
16
  }
12
17
  exports.PositionDirection = PositionDirection;
@@ -17,6 +22,7 @@ class OracleSource {
17
22
  exports.OracleSource = OracleSource;
18
23
  OracleSource.PYTH = { pyth: {} };
19
24
  OracleSource.SWITCHBOARD = { switchboard: {} };
25
+ OracleSource.QUOTE_ASSET = { quoteAsset: {} };
20
26
  class OrderType {
21
27
  }
22
28
  exports.OrderType = OrderType;
@@ -53,6 +59,12 @@ function isVariant(object, type) {
53
59
  return object.hasOwnProperty(type);
54
60
  }
55
61
  exports.isVariant = isVariant;
62
+ function isOneOfVariant(object, types) {
63
+ return types.reduce((result, type) => {
64
+ return result || object.hasOwnProperty(type);
65
+ }, false);
66
+ }
67
+ exports.isOneOfVariant = isOneOfVariant;
56
68
  var TradeSide;
57
69
  (function (TradeSide) {
58
70
  TradeSide[TradeSide["None"] = 0] = "None";
@@ -0,0 +1,4 @@
1
+ export declare const MAX_NAME_LENGTH = 32;
2
+ export declare const DEFAULT_USER_NAME = "Main Account";
3
+ export declare function encodeName(name: string): number[];
4
+ export declare function decodeName(bytes: number[]): string;
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.decodeName = exports.encodeName = exports.DEFAULT_USER_NAME = exports.MAX_NAME_LENGTH = void 0;
4
+ exports.MAX_NAME_LENGTH = 32;
5
+ exports.DEFAULT_USER_NAME = 'Main Account';
6
+ function encodeName(name) {
7
+ if (name.length > exports.MAX_NAME_LENGTH) {
8
+ throw Error(`User name (${name}) longer than 32 characters`);
9
+ }
10
+ const buffer = Buffer.alloc(32);
11
+ buffer.fill(name);
12
+ buffer.fill(' ', name.length);
13
+ return Array(...buffer);
14
+ }
15
+ exports.encodeName = encodeName;
16
+ function decodeName(bytes) {
17
+ const buffer = Buffer.from(bytes);
18
+ return buffer.toString('utf8').trim();
19
+ }
20
+ exports.decodeName = decodeName;
@@ -1,27 +1,16 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.findComputeUnitConsumption = void 0;
13
- function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- const tx = yield connection.getTransaction(txSignature, { commitment });
16
- const computeUnits = [];
17
- const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of 200000 compute units`);
18
- tx.meta.logMessages.forEach((logMessage) => {
19
- const match = logMessage.match(regex);
20
- if (match && match[1]) {
21
- computeUnits.push(match[1]);
22
- }
23
- });
24
- return computeUnits;
4
+ async function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
5
+ const tx = await connection.getTransaction(txSignature, { commitment });
6
+ const computeUnits = [];
7
+ const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of 200000 compute units`);
8
+ tx.meta.logMessages.forEach((logMessage) => {
9
+ const match = logMessage.match(regex);
10
+ if (match && match[1]) {
11
+ computeUnits.push(match[1]);
12
+ }
25
13
  });
14
+ return computeUnits;
26
15
  }
27
16
  exports.findComputeUnitConsumption = findComputeUnitConsumption;
package/lib/util/tps.js CHANGED
@@ -1,27 +1,16 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.estimateTps = void 0;
13
- function estimateTps(programId, connection, failed) {
14
- return __awaiter(this, void 0, void 0, function* () {
15
- let signatures = yield connection.getSignaturesForAddress(programId, undefined, 'finalized');
16
- if (failed) {
17
- signatures = signatures.filter((signature) => signature.err);
18
- }
19
- const numberOfSignatures = signatures.length;
20
- if (numberOfSignatures === 0) {
21
- return 0;
22
- }
23
- return (numberOfSignatures /
24
- (signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
25
- });
4
+ async function estimateTps(programId, connection, failed) {
5
+ let signatures = await connection.getSignaturesForAddress(programId, undefined, 'finalized');
6
+ if (failed) {
7
+ signatures = signatures.filter((signature) => signature.err);
8
+ }
9
+ const numberOfSignatures = signatures.length;
10
+ if (numberOfSignatures === 0) {
11
+ return 0;
12
+ }
13
+ return (numberOfSignatures /
14
+ (signatures[0].blockTime - signatures[numberOfSignatures - 1].blockTime));
26
15
  }
27
16
  exports.estimateTps = estimateTps;
package/lib/wallet.js CHANGED
@@ -1,31 +1,18 @@
1
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
2
  Object.defineProperty(exports, "__esModule", { value: true });
12
3
  exports.Wallet = void 0;
13
4
  class Wallet {
14
5
  constructor(payer) {
15
6
  this.payer = payer;
16
7
  }
17
- signTransaction(tx) {
18
- return __awaiter(this, void 0, void 0, function* () {
19
- tx.partialSign(this.payer);
20
- return tx;
21
- });
8
+ async signTransaction(tx) {
9
+ tx.partialSign(this.payer);
10
+ return tx;
22
11
  }
23
- signAllTransactions(txs) {
24
- return __awaiter(this, void 0, void 0, function* () {
25
- return txs.map((t) => {
26
- t.partialSign(this.payer);
27
- return t;
28
- });
12
+ async signAllTransactions(txs) {
13
+ return txs.map((t) => {
14
+ t.partialSign(this.payer);
15
+ return t;
29
16
  });
30
17
  }
31
18
  get publicKey() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.36-master.5",
3
+ "version": "0.2.0-master.0",
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": [
@@ -31,17 +32,23 @@
31
32
  "@project-serum/anchor": "0.24.2",
32
33
  "@pythnetwork/client": "^2.5.1",
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/mocha": "^9.1.1",
40
43
  "@typescript-eslint/eslint-plugin": "^4.28.0",
41
44
  "@typescript-eslint/parser": "^4.28.0",
45
+ "@types/jest": "^28.1.3",
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": {
@@ -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,13 +17,14 @@ 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
24
24
  loadPromise?: Promise<void>;
25
25
  loadPromiseResolver: () => void;
26
26
  lastTimeLoadingPromiseCleared = Date.now();
27
+ mostRecentSlot = 0;
27
28
 
28
29
  public constructor(
29
30
  connection: Connection,
@@ -37,7 +38,7 @@ export class BulkAccountLoader {
37
38
 
38
39
  public addAccount(
39
40
  publicKey: PublicKey,
40
- callback: (buffer: Buffer) => void
41
+ callback: (buffer: Buffer, slot: number) => void
41
42
  ): string {
42
43
  const existingSize = this.accountsToLoad.size;
43
44
 
@@ -46,7 +47,10 @@ export class BulkAccountLoader {
46
47
  if (existingAccountToLoad) {
47
48
  existingAccountToLoad.callbacks.set(callbackId, callback);
48
49
  } else {
49
- const callbacks = new Map<string, (buffer: Buffer) => void>();
50
+ const callbacks = new Map<
51
+ string,
52
+ (buffer: Buffer, slot: number) => void
53
+ >();
50
54
  callbacks.set(callbackId, callback);
51
55
  const newAccountToLoad = {
52
56
  publicKey,
@@ -159,10 +163,14 @@ export class BulkAccountLoader {
159
163
 
160
164
  const newSlot = rpcResponse.result.context.slot;
161
165
 
166
+ if (newSlot > this.mostRecentSlot) {
167
+ this.mostRecentSlot = newSlot;
168
+ }
169
+
162
170
  for (const i in accountsToLoad) {
163
171
  const accountToLoad = accountsToLoad[i];
164
172
  const key = accountToLoad.publicKey.toString();
165
- const oldRPCResponse = this.accountData.get(key);
173
+ const oldRPCResponse = this.bufferAndSlotMap.get(key);
166
174
 
167
175
  let newBuffer: Buffer | undefined = undefined;
168
176
  if (rpcResponse.result.value[i]) {
@@ -172,11 +180,11 @@ export class BulkAccountLoader {
172
180
  }
173
181
 
174
182
  if (!oldRPCResponse) {
175
- this.accountData.set(key, {
183
+ this.bufferAndSlotMap.set(key, {
176
184
  slot: newSlot,
177
185
  buffer: newBuffer,
178
186
  });
179
- this.handleAccountCallbacks(accountToLoad, newBuffer);
187
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
180
188
  continue;
181
189
  }
182
190
 
@@ -186,24 +194,27 @@ export class BulkAccountLoader {
186
194
 
187
195
  const oldBuffer = oldRPCResponse.buffer;
188
196
  if (newBuffer && (!oldBuffer || !newBuffer.equals(oldBuffer))) {
189
- this.accountData.set(key, {
197
+ this.bufferAndSlotMap.set(key, {
190
198
  slot: newSlot,
191
199
  buffer: newBuffer,
192
200
  });
193
- this.handleAccountCallbacks(accountToLoad, newBuffer);
201
+ this.handleAccountCallbacks(accountToLoad, newBuffer, newSlot);
194
202
  }
195
203
  }
196
204
  }
197
205
 
198
- handleAccountCallbacks(accountToLoad: AccountToLoad, buffer: Buffer): void {
206
+ handleAccountCallbacks(
207
+ accountToLoad: AccountToLoad,
208
+ buffer: Buffer,
209
+ slot: number
210
+ ): void {
199
211
  for (const [_, callback] of accountToLoad.callbacks) {
200
- callback(buffer);
212
+ callback(buffer, slot);
201
213
  }
202
214
  }
203
215
 
204
- public getAccountData(publicKey: PublicKey): Buffer | undefined {
205
- const accountData = this.accountData.get(publicKey.toString());
206
- return accountData?.buffer;
216
+ public getBufferAndSlot(publicKey: PublicKey): BufferAndSlot | undefined {
217
+ return this.bufferAndSlotMap.get(publicKey.toString());
207
218
  }
208
219
 
209
220
  public startPolling(): void {
@@ -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,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
+ }