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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (234) hide show
  1. package/README.md +27 -27
  2. package/lib/accounts/bulkAccountLoader.d.ts +2 -0
  3. package/lib/accounts/bulkAccountLoader.js +36 -29
  4. package/lib/accounts/bulkUserStatsSubscription.d.ts +7 -0
  5. package/lib/accounts/bulkUserStatsSubscription.js +21 -0
  6. package/lib/accounts/bulkUserSubscription.d.ts +2 -2
  7. package/lib/accounts/bulkUserSubscription.js +0 -1
  8. package/lib/accounts/fetch.d.ts +2 -1
  9. package/lib/accounts/fetch.js +9 -1
  10. package/lib/accounts/{pollingClearingHouseAccountSubscriber.d.ts → pollingDriftClientAccountSubscriber.d.ts} +20 -25
  11. package/lib/accounts/{pollingClearingHouseAccountSubscriber.js → pollingDriftClientAccountSubscriber.js} +45 -49
  12. package/lib/accounts/{pollingOracleSubscriber.d.ts → pollingOracleAccountSubscriber.d.ts} +2 -2
  13. package/lib/accounts/{pollingOracleSubscriber.js → pollingOracleAccountSubscriber.js} +3 -3
  14. package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +27 -0
  15. package/lib/accounts/pollingUserStatsAccountSubscriber.js +113 -0
  16. package/lib/accounts/types.d.ts +26 -15
  17. package/lib/accounts/webSocketDriftClientAccountSubscriber.d.ts +49 -0
  18. package/lib/accounts/{webSocketClearingHouseAccountSubscriber.js → webSocketDriftClientAccountSubscriber.js} +47 -45
  19. package/lib/accounts/webSocketUserStatsAccountSubsriber.d.ts +20 -0
  20. package/lib/accounts/webSocketUserStatsAccountSubsriber.js +47 -0
  21. package/lib/addresses/marketAddresses.d.ts +1 -3
  22. package/lib/addresses/marketAddresses.js +1 -1
  23. package/lib/addresses/pda.d.ts +15 -9
  24. package/lib/addresses/pda.js +73 -35
  25. package/lib/adminClient.d.ts +65 -0
  26. package/lib/adminClient.js +637 -0
  27. package/lib/config.d.ts +9 -9
  28. package/lib/config.js +25 -21
  29. package/lib/constants/numericConstants.d.ts +30 -12
  30. package/lib/constants/numericConstants.js +41 -21
  31. package/lib/constants/perpMarkets.d.ts +18 -0
  32. package/lib/constants/{markets.js → perpMarkets.js} +7 -7
  33. package/lib/constants/spotMarkets.d.ts +19 -0
  34. package/lib/constants/spotMarkets.js +53 -0
  35. package/lib/dlob/DLOB.d.ts +82 -0
  36. package/lib/dlob/DLOB.js +696 -0
  37. package/lib/dlob/DLOBNode.d.ts +54 -0
  38. package/lib/dlob/DLOBNode.js +77 -0
  39. package/lib/dlob/NodeList.d.ts +27 -0
  40. package/lib/dlob/NodeList.js +144 -0
  41. package/lib/driftClient.d.ts +233 -0
  42. package/lib/driftClient.js +2096 -0
  43. package/lib/{clearingHouseConfig.d.ts → driftClientConfig.d.ts} +9 -9
  44. package/lib/{clearingHouseConfig.js → driftClientConfig.js} +0 -0
  45. package/lib/events/eventList.js +3 -0
  46. package/lib/events/eventSubscriber.d.ts +5 -2
  47. package/lib/events/eventSubscriber.js +25 -11
  48. package/lib/events/fetchLogs.d.ts +13 -2
  49. package/lib/events/fetchLogs.js +40 -12
  50. package/lib/events/pollingLogProvider.d.ts +2 -1
  51. package/lib/events/pollingLogProvider.js +7 -3
  52. package/lib/events/sort.js +8 -11
  53. package/lib/events/types.d.ts +9 -3
  54. package/lib/events/types.js +6 -0
  55. package/lib/events/webSocketLogProvider.js +1 -1
  56. package/lib/examples/makeTradeExample.js +30 -18
  57. package/lib/factory/bigNum.d.ts +8 -4
  58. package/lib/factory/bigNum.js +109 -19
  59. package/lib/idl/drift.json +8250 -0
  60. package/lib/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  61. package/lib/index.d.ts +30 -13
  62. package/lib/index.js +30 -13
  63. package/lib/math/amm.d.ts +9 -6
  64. package/lib/math/amm.js +91 -38
  65. package/lib/math/conversion.js +1 -1
  66. package/lib/math/exchangeStatus.d.ts +4 -0
  67. package/lib/math/exchangeStatus.js +18 -0
  68. package/lib/math/funding.d.ts +6 -6
  69. package/lib/math/funding.js +23 -21
  70. package/lib/math/insurance.d.ts +4 -0
  71. package/lib/math/insurance.js +27 -0
  72. package/lib/math/margin.d.ts +11 -0
  73. package/lib/math/margin.js +82 -0
  74. package/lib/math/market.d.ts +14 -9
  75. package/lib/math/market.js +70 -10
  76. package/lib/math/oracles.d.ts +4 -0
  77. package/lib/math/oracles.js +36 -8
  78. package/lib/math/orders.d.ts +14 -6
  79. package/lib/math/orders.js +90 -17
  80. package/lib/math/position.d.ts +27 -13
  81. package/lib/math/position.js +92 -36
  82. package/lib/math/repeg.js +17 -8
  83. package/lib/math/spotBalance.d.ts +22 -0
  84. package/lib/math/spotBalance.js +192 -0
  85. package/lib/math/spotMarket.d.ts +4 -0
  86. package/lib/math/spotMarket.js +8 -0
  87. package/lib/math/spotPosition.d.ts +6 -0
  88. package/lib/math/spotPosition.js +23 -0
  89. package/lib/math/trade.d.ts +10 -10
  90. package/lib/math/trade.js +27 -31
  91. package/lib/oracles/pythClient.js +1 -1
  92. package/lib/oracles/quoteAssetOracleClient.js +1 -1
  93. package/lib/oracles/switchboardClient.js +1 -1
  94. package/lib/orderParams.d.ts +4 -4
  95. package/lib/orderParams.js +12 -4
  96. package/lib/serum/serumFulfillmentConfigMap.d.ts +10 -0
  97. package/lib/serum/serumFulfillmentConfigMap.js +17 -0
  98. package/lib/serum/serumSubscriber.d.ts +27 -0
  99. package/lib/serum/serumSubscriber.js +56 -0
  100. package/lib/serum/types.d.ts +11 -0
  101. package/lib/{clearingHouseUserConfig.js → serum/types.js} +0 -0
  102. package/lib/slot/SlotSubscriber.d.ts +7 -0
  103. package/lib/slot/SlotSubscriber.js +3 -0
  104. package/lib/{mockUSDCFaucet.d.ts → tokenFaucet.d.ts} +8 -5
  105. package/lib/{mockUSDCFaucet.js → tokenFaucet.js} +63 -51
  106. package/lib/tx/retryTxSender.d.ts +1 -1
  107. package/lib/tx/retryTxSender.js +13 -4
  108. package/lib/tx/types.d.ts +1 -1
  109. package/lib/tx/utils.js +1 -1
  110. package/lib/types.d.ts +589 -196
  111. package/lib/types.js +108 -17
  112. package/lib/user.d.ts +226 -0
  113. package/lib/user.js +949 -0
  114. package/lib/userConfig.d.ts +14 -0
  115. package/lib/userConfig.js +2 -0
  116. package/lib/userMap/userMap.d.ts +41 -0
  117. package/lib/userMap/userMap.js +85 -0
  118. package/lib/userMap/userStatsMap.d.ts +19 -0
  119. package/lib/userMap/userStatsMap.js +68 -0
  120. package/lib/userName.d.ts +1 -0
  121. package/lib/userName.js +3 -2
  122. package/lib/userStats.d.ts +18 -0
  123. package/lib/userStats.js +49 -0
  124. package/lib/userStatsConfig.d.ts +14 -0
  125. package/lib/userStatsConfig.js +2 -0
  126. package/lib/util/computeUnits.js +1 -1
  127. package/lib/util/getTokenAddress.d.ts +2 -0
  128. package/lib/util/getTokenAddress.js +9 -0
  129. package/package.json +10 -3
  130. package/src/accounts/bulkAccountLoader.ts +44 -34
  131. package/src/accounts/bulkUserStatsSubscription.ts +33 -0
  132. package/src/accounts/bulkUserSubscription.ts +2 -3
  133. package/src/accounts/fetch.ts +27 -2
  134. package/src/accounts/{pollingClearingHouseAccountSubscriber.ts → pollingDriftClientAccountSubscriber.ts} +65 -75
  135. package/src/accounts/{pollingOracleSubscriber.ts → pollingOracleAccountSubscriber.ts} +2 -2
  136. package/src/accounts/pollingUserStatsAccountSubscriber.ts +172 -0
  137. package/src/accounts/types.ts +35 -15
  138. package/src/accounts/{webSocketClearingHouseAccountSubscriber.ts → webSocketDriftClientAccountSubscriber.ts} +78 -73
  139. package/src/accounts/webSocketUserStatsAccountSubsriber.ts +80 -0
  140. package/src/addresses/marketAddresses.ts +3 -4
  141. package/src/addresses/pda.ts +105 -33
  142. package/src/adminClient.ts +1207 -0
  143. package/src/config.ts +37 -31
  144. package/src/constants/numericConstants.ts +58 -24
  145. package/src/constants/{markets.ts → perpMarkets.ts} +10 -10
  146. package/src/constants/spotMarkets.ts +73 -0
  147. package/src/dlob/DLOB.ts +1123 -0
  148. package/src/dlob/DLOBNode.ts +155 -0
  149. package/src/dlob/NodeList.ts +195 -0
  150. package/src/driftClient.ts +3564 -0
  151. package/src/{clearingHouseConfig.ts → driftClientConfig.ts} +9 -8
  152. package/src/events/eventList.ts +3 -0
  153. package/src/events/eventSubscriber.ts +36 -14
  154. package/src/events/fetchLogs.ts +55 -13
  155. package/src/events/pollingLogProvider.ts +11 -3
  156. package/src/events/sort.ts +11 -15
  157. package/src/events/types.ts +21 -2
  158. package/src/events/webSocketLogProvider.ts +1 -1
  159. package/src/examples/makeTradeExample.ts +44 -28
  160. package/src/factory/bigNum.ts +150 -22
  161. package/src/idl/drift.json +8250 -0
  162. package/src/idl/pyth.json +98 -2
  163. package/src/idl/{mock_usdc_faucet.json → token_faucet.json} +46 -23
  164. package/src/index.ts +30 -13
  165. package/src/math/amm.ts +161 -48
  166. package/src/math/conversion.ts +2 -2
  167. package/src/math/exchangeStatus.ts +31 -0
  168. package/src/math/funding.ts +41 -31
  169. package/src/math/insurance.ts +35 -0
  170. package/src/math/margin.ts +133 -0
  171. package/src/math/market.ts +143 -14
  172. package/src/math/oracles.ts +63 -9
  173. package/src/math/orders.ts +163 -26
  174. package/src/math/position.ts +136 -58
  175. package/src/math/repeg.ts +19 -9
  176. package/src/math/spotBalance.ts +319 -0
  177. package/src/math/spotMarket.ts +9 -0
  178. package/src/math/spotPosition.ts +47 -0
  179. package/src/math/trade.ts +33 -37
  180. package/src/oracles/pythClient.ts +2 -2
  181. package/src/oracles/quoteAssetOracleClient.ts +2 -2
  182. package/src/oracles/switchboardClient.ts +2 -2
  183. package/src/orderParams.ts +16 -8
  184. package/src/serum/serumFulfillmentConfigMap.ts +26 -0
  185. package/src/serum/serumSubscriber.ts +99 -0
  186. package/src/serum/types.ts +13 -0
  187. package/src/slot/SlotSubscriber.ts +11 -1
  188. package/src/{mockUSDCFaucet.ts → tokenFaucet.ts} +82 -70
  189. package/src/tx/retryTxSender.ts +16 -5
  190. package/src/tx/types.ts +2 -1
  191. package/src/tx/utils.ts +1 -1
  192. package/src/types.ts +572 -178
  193. package/src/user.ts +1582 -0
  194. package/src/{clearingHouseUserConfig.ts → userConfig.ts} +5 -5
  195. package/src/userMap/userMap.ts +124 -0
  196. package/src/userMap/userStatsMap.ts +108 -0
  197. package/src/userName.ts +2 -1
  198. package/src/userStats.ts +75 -0
  199. package/src/userStatsConfig.ts +18 -0
  200. package/src/util/computeUnits.ts +1 -1
  201. package/src/util/getTokenAddress.ts +18 -0
  202. package/tests/bn/test.ts +46 -11
  203. package/tests/dlob/helpers.ts +611 -0
  204. package/tests/dlob/test.ts +4588 -0
  205. package/lib/accounts/webSocketClearingHouseAccountSubscriber.d.ts +0 -49
  206. package/lib/admin.d.ts +0 -44
  207. package/lib/admin.js +0 -433
  208. package/lib/clearingHouse.d.ts +0 -133
  209. package/lib/clearingHouse.js +0 -931
  210. package/lib/clearingHouseUser.d.ts +0 -187
  211. package/lib/clearingHouseUser.js +0 -643
  212. package/lib/clearingHouseUserConfig.d.ts +0 -14
  213. package/lib/constants/banks.d.ts +0 -16
  214. package/lib/constants/banks.js +0 -34
  215. package/lib/constants/markets.d.ts +0 -19
  216. package/lib/idl/clearing_house.json +0 -3998
  217. package/lib/math/bankBalance.d.ts +0 -9
  218. package/lib/math/bankBalance.js +0 -75
  219. package/lib/math/state.d.ts +0 -8
  220. package/lib/math/state.js +0 -15
  221. package/lib/orders.d.ts +0 -8
  222. package/lib/orders.js +0 -134
  223. package/src/admin.ts +0 -722
  224. package/src/clearingHouse.ts +0 -1451
  225. package/src/clearingHouseUser.ts +0 -989
  226. package/src/constants/banks.ts +0 -43
  227. package/src/idl/clearing_house.json +0 -3998
  228. package/src/math/bankBalance.ts +0 -112
  229. package/src/math/state.ts +0 -14
  230. package/src/math/utils.js +0 -27
  231. package/src/math/utils.js.map +0 -1
  232. package/src/orders.ts +0 -244
  233. package/src/util/computeUnits.js +0 -17
  234. package/src/util/computeUnits.js.map +0 -1
@@ -0,0 +1,14 @@
1
+ import { DriftClient } from './driftClient';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { BulkAccountLoader } from './accounts/bulkAccountLoader';
4
+ export declare type UserConfig = {
5
+ accountSubscription?: UserSubscriptionConfig;
6
+ driftClient: DriftClient;
7
+ userAccountPublicKey: PublicKey;
8
+ };
9
+ export declare type UserSubscriptionConfig = {
10
+ type: 'websocket';
11
+ } | {
12
+ type: 'polling';
13
+ accountLoader: BulkAccountLoader;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,41 @@
1
+ import { User, DriftClient, OrderRecord, UserSubscriptionConfig } from '..';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ export interface UserMapInterface {
4
+ fetchAllUsers(): Promise<void>;
5
+ addPubkey(userAccountPublicKey: PublicKey): Promise<void>;
6
+ has(key: string): boolean;
7
+ get(key: string): User | undefined;
8
+ mustGet(key: string): Promise<User>;
9
+ getUserAuthority(key: string): PublicKey | undefined;
10
+ updateWithOrderRecord(record: OrderRecord): Promise<void>;
11
+ values(): IterableIterator<User>;
12
+ }
13
+ export declare class UserMap implements UserMapInterface {
14
+ private userMap;
15
+ private driftClient;
16
+ private accountSubscription;
17
+ constructor(driftClient: DriftClient, accountSubscription: UserSubscriptionConfig);
18
+ fetchAllUsers(): Promise<void>;
19
+ addPubkey(userAccountPublicKey: PublicKey): Promise<void>;
20
+ has(key: string): boolean;
21
+ /**
22
+ * gets the User for a particular userAccountPublicKey, if no User exists, undefined is returned
23
+ * @param key userAccountPublicKey to get User for
24
+ * @returns user User | undefined
25
+ */
26
+ get(key: string): User | undefined;
27
+ /**
28
+ * gets the User for a particular userAccountPublicKey, if no User exists, new one is created
29
+ * @param key userAccountPublicKey to get User for
30
+ * @returns User
31
+ */
32
+ mustGet(key: string): Promise<User>;
33
+ /**
34
+ * gets the Authority for a particular userAccountPublicKey, if no User exists, undefined is returned
35
+ * @param key userAccountPublicKey to get User for
36
+ * @returns authority PublicKey | undefined
37
+ */
38
+ getUserAuthority(key: string): PublicKey | undefined;
39
+ updateWithOrderRecord(record: OrderRecord): Promise<void>;
40
+ values(): IterableIterator<User>;
41
+ }
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserMap = void 0;
4
+ const __1 = require("..");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ class UserMap {
7
+ constructor(driftClient, accountSubscription) {
8
+ this.userMap = new Map();
9
+ this.driftClient = driftClient;
10
+ this.accountSubscription = accountSubscription;
11
+ }
12
+ async fetchAllUsers() {
13
+ const userArray = [];
14
+ const programUserAccounts = (await this.driftClient.program.account.user.all());
15
+ for (const programUserAccount of programUserAccounts) {
16
+ if (this.userMap.has(programUserAccount.publicKey.toString())) {
17
+ continue;
18
+ }
19
+ const user = new __1.User({
20
+ driftClient: this.driftClient,
21
+ userAccountPublicKey: programUserAccount.publicKey,
22
+ accountSubscription: this.accountSubscription,
23
+ });
24
+ userArray.push(user);
25
+ }
26
+ if (this.accountSubscription.type === 'polling') {
27
+ await (0, __1.bulkPollingUserSubscribe)(userArray, this.accountSubscription.accountLoader);
28
+ }
29
+ for (const user of userArray) {
30
+ this.userMap.set(user.getUserAccountPublicKey().toString(), user);
31
+ }
32
+ }
33
+ async addPubkey(userAccountPublicKey) {
34
+ const user = new __1.User({
35
+ driftClient: this.driftClient,
36
+ userAccountPublicKey,
37
+ accountSubscription: this.accountSubscription,
38
+ });
39
+ await user.subscribe();
40
+ this.userMap.set(userAccountPublicKey.toString(), user);
41
+ }
42
+ has(key) {
43
+ return this.userMap.has(key);
44
+ }
45
+ /**
46
+ * gets the User for a particular userAccountPublicKey, if no User exists, undefined is returned
47
+ * @param key userAccountPublicKey to get User for
48
+ * @returns user User | undefined
49
+ */
50
+ get(key) {
51
+ return this.userMap.get(key);
52
+ }
53
+ /**
54
+ * gets the User for a particular userAccountPublicKey, if no User exists, new one is created
55
+ * @param key userAccountPublicKey to get User for
56
+ * @returns User
57
+ */
58
+ async mustGet(key) {
59
+ if (!this.has(key)) {
60
+ await this.addPubkey(new web3_js_1.PublicKey(key));
61
+ }
62
+ const user = this.userMap.get(key);
63
+ await user.fetchAccounts();
64
+ return user;
65
+ }
66
+ /**
67
+ * gets the Authority for a particular userAccountPublicKey, if no User exists, undefined is returned
68
+ * @param key userAccountPublicKey to get User for
69
+ * @returns authority PublicKey | undefined
70
+ */
71
+ getUserAuthority(key) {
72
+ const chUser = this.userMap.get(key);
73
+ if (!chUser) {
74
+ return undefined;
75
+ }
76
+ return chUser.getUserAccount().authority;
77
+ }
78
+ async updateWithOrderRecord(record) {
79
+ await this.addPubkey(record.user);
80
+ }
81
+ values() {
82
+ return this.userMap.values();
83
+ }
84
+ }
85
+ exports.UserMap = UserMap;
@@ -0,0 +1,19 @@
1
+ import { DriftClient, OrderRecord, UserStats, UserStatsSubscriptionConfig } from '..';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { UserMap } from './userMap';
4
+ export declare class UserStatsMap {
5
+ /**
6
+ * map from authority pubkey to UserStats
7
+ */
8
+ private userStatsMap;
9
+ private driftClient;
10
+ private accountSubscription;
11
+ constructor(driftClient: DriftClient, accountSubscription: UserStatsSubscriptionConfig);
12
+ fetchAllUserStats(): Promise<void>;
13
+ addUserStat(authority: PublicKey): Promise<void>;
14
+ updateWithOrderRecord(record: OrderRecord, userMap: UserMap): Promise<void>;
15
+ has(authorityPublicKey: string): boolean;
16
+ get(authorityPublicKey: string): UserStats;
17
+ mustGet(authorityPublicKey: string): Promise<UserStats>;
18
+ values(): IterableIterator<UserStats>;
19
+ }
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserStatsMap = void 0;
4
+ const __1 = require("..");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ class UserStatsMap {
7
+ constructor(driftClient, accountSubscription) {
8
+ /**
9
+ * map from authority pubkey to UserStats
10
+ */
11
+ this.userStatsMap = new Map();
12
+ this.driftClient = driftClient;
13
+ this.accountSubscription = accountSubscription;
14
+ }
15
+ async fetchAllUserStats() {
16
+ const userStatArray = [];
17
+ const programUserAccounts = (await this.driftClient.program.account.userStats.all());
18
+ for (const programUserAccount of programUserAccounts) {
19
+ const userStat = programUserAccount.account;
20
+ if (this.userStatsMap.has(userStat.authority.toString())) {
21
+ continue;
22
+ }
23
+ const chUserStat = new __1.UserStats({
24
+ driftClient: this.driftClient,
25
+ userStatsAccountPublicKey: (0, __1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, userStat.authority),
26
+ accountSubscription: this.accountSubscription,
27
+ });
28
+ userStatArray.push(chUserStat);
29
+ }
30
+ if (this.accountSubscription.type === 'polling') {
31
+ await (0, __1.bulkPollingUserStatsSubscribe)(userStatArray, this.accountSubscription.accountLoader);
32
+ }
33
+ for (const userStat of userStatArray) {
34
+ this.userStatsMap.set(userStat.getAccount().authority.toString(), userStat);
35
+ }
36
+ }
37
+ async addUserStat(authority) {
38
+ const userStat = new __1.UserStats({
39
+ driftClient: this.driftClient,
40
+ userStatsAccountPublicKey: (0, __1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, authority),
41
+ accountSubscription: this.accountSubscription,
42
+ });
43
+ await userStat.subscribe();
44
+ this.userStatsMap.set(authority.toString(), userStat);
45
+ }
46
+ async updateWithOrderRecord(record, userMap) {
47
+ if (!this.has(record.user.toString())) {
48
+ const takerUserAccount = await userMap.mustGet(record.user.toString());
49
+ this.addUserStat(takerUserAccount.getUserAccount().authority);
50
+ }
51
+ }
52
+ has(authorityPublicKey) {
53
+ return this.userStatsMap.has(authorityPublicKey);
54
+ }
55
+ get(authorityPublicKey) {
56
+ return this.userStatsMap.get(authorityPublicKey);
57
+ }
58
+ async mustGet(authorityPublicKey) {
59
+ if (!this.has(authorityPublicKey)) {
60
+ await this.addUserStat(new web3_js_1.PublicKey(authorityPublicKey));
61
+ }
62
+ return this.get(authorityPublicKey);
63
+ }
64
+ values() {
65
+ return this.userStatsMap.values();
66
+ }
67
+ }
68
+ exports.UserStatsMap = UserStatsMap;
package/lib/userName.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export declare const MAX_NAME_LENGTH = 32;
2
2
  export declare const DEFAULT_USER_NAME = "Main Account";
3
+ export declare const DEFAULT_MARKET_NAME = "Default Market Name";
3
4
  export declare function encodeName(name: string): number[];
4
5
  export declare function decodeName(bytes: number[]): string;
package/lib/userName.js CHANGED
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decodeName = exports.encodeName = exports.DEFAULT_USER_NAME = exports.MAX_NAME_LENGTH = void 0;
3
+ exports.decodeName = exports.encodeName = exports.DEFAULT_MARKET_NAME = exports.DEFAULT_USER_NAME = exports.MAX_NAME_LENGTH = void 0;
4
4
  exports.MAX_NAME_LENGTH = 32;
5
5
  exports.DEFAULT_USER_NAME = 'Main Account';
6
+ exports.DEFAULT_MARKET_NAME = 'Default Market Name';
6
7
  function encodeName(name) {
7
8
  if (name.length > exports.MAX_NAME_LENGTH) {
8
- throw Error(`User name (${name}) longer than 32 characters`);
9
+ throw Error(`Name (${name}) longer than 32 characters`);
9
10
  }
10
11
  const buffer = Buffer.alloc(32);
11
12
  buffer.fill(name);
@@ -0,0 +1,18 @@
1
+ import { DriftClient } from './driftClient';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { DataAndSlot, UserStatsAccountSubscriber } from './accounts/types';
4
+ import { UserStatsConfig } from './userStatsConfig';
5
+ import { ReferrerInfo, UserStatsAccount } from './types';
6
+ export declare class UserStats {
7
+ driftClient: DriftClient;
8
+ userStatsAccountPublicKey: PublicKey;
9
+ accountSubscriber: UserStatsAccountSubscriber;
10
+ isSubscribed: boolean;
11
+ constructor(config: UserStatsConfig);
12
+ subscribe(): Promise<boolean>;
13
+ fetchAccounts(): Promise<void>;
14
+ unsubscribe(): Promise<void>;
15
+ getAccountAndSlot(): DataAndSlot<UserStatsAccount>;
16
+ getAccount(): UserStatsAccount;
17
+ getReferrerInfo(): ReferrerInfo | undefined;
18
+ }
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.UserStats = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const pollingUserStatsAccountSubscriber_1 = require("./accounts/pollingUserStatsAccountSubscriber");
6
+ const webSocketUserStatsAccountSubsriber_1 = require("./accounts/webSocketUserStatsAccountSubsriber");
7
+ const pda_1 = require("./addresses/pda");
8
+ class UserStats {
9
+ constructor(config) {
10
+ var _a;
11
+ this.driftClient = config.driftClient;
12
+ this.userStatsAccountPublicKey = config.userStatsAccountPublicKey;
13
+ if (((_a = config.accountSubscription) === null || _a === void 0 ? void 0 : _a.type) === 'polling') {
14
+ this.accountSubscriber = new pollingUserStatsAccountSubscriber_1.PollingUserStatsAccountSubscriber(config.driftClient.program, config.userStatsAccountPublicKey, config.accountSubscription.accountLoader);
15
+ }
16
+ else {
17
+ this.accountSubscriber = new webSocketUserStatsAccountSubsriber_1.WebSocketUserStatsAccountSubscriber(config.driftClient.program, config.userStatsAccountPublicKey);
18
+ }
19
+ }
20
+ async subscribe() {
21
+ this.isSubscribed = await this.accountSubscriber.subscribe();
22
+ return this.isSubscribed;
23
+ }
24
+ async fetchAccounts() {
25
+ await this.accountSubscriber.fetch();
26
+ }
27
+ async unsubscribe() {
28
+ await this.accountSubscriber.unsubscribe();
29
+ this.isSubscribed = false;
30
+ }
31
+ getAccountAndSlot() {
32
+ return this.accountSubscriber.getUserStatsAccountAndSlot();
33
+ }
34
+ getAccount() {
35
+ return this.accountSubscriber.getUserStatsAccountAndSlot().data;
36
+ }
37
+ getReferrerInfo() {
38
+ if (this.getAccount().referrer.equals(web3_js_1.PublicKey.default)) {
39
+ return undefined;
40
+ }
41
+ else {
42
+ return {
43
+ referrer: (0, pda_1.getUserAccountPublicKeySync)(this.driftClient.program.programId, this.getAccount().referrer, 0),
44
+ referrerStats: (0, pda_1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, this.getAccount().referrer),
45
+ };
46
+ }
47
+ }
48
+ }
49
+ exports.UserStats = UserStats;
@@ -0,0 +1,14 @@
1
+ import { DriftClient } from './driftClient';
2
+ import { PublicKey } from '@solana/web3.js';
3
+ import { BulkAccountLoader } from './accounts/bulkAccountLoader';
4
+ export declare type UserStatsConfig = {
5
+ accountSubscription?: UserStatsSubscriptionConfig;
6
+ driftClient: DriftClient;
7
+ userStatsAccountPublicKey: PublicKey;
8
+ };
9
+ export declare type UserStatsSubscriptionConfig = {
10
+ type: 'websocket';
11
+ } | {
12
+ type: 'polling';
13
+ accountLoader: BulkAccountLoader;
14
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -4,7 +4,7 @@ exports.findComputeUnitConsumption = void 0;
4
4
  async function findComputeUnitConsumption(programId, connection, txSignature, commitment = 'confirmed') {
5
5
  const tx = await connection.getTransaction(txSignature, { commitment });
6
6
  const computeUnits = [];
7
- const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of 200000 compute units`);
7
+ const regex = new RegExp(`Program ${programId.toString()} consumed ([0-9]{0,6}) of ([0-9]{0,7}) compute units`);
8
8
  tx.meta.logMessages.forEach((logMessage) => {
9
9
  const match = logMessage.match(regex);
10
10
  if (match && match[1]) {
@@ -0,0 +1,2 @@
1
+ import { PublicKey } from '@solana/web3.js';
2
+ export declare const getTokenAddress: (mintAddress: string, userPubKey: string) => Promise<PublicKey>;
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getTokenAddress = void 0;
4
+ const spl_token_1 = require("@solana/spl-token");
5
+ const web3_js_1 = require("@solana/web3.js");
6
+ const getTokenAddress = (mintAddress, userPubKey) => {
7
+ return spl_token_1.Token.getAssociatedTokenAddress(spl_token_1.ASSOCIATED_TOKEN_PROGRAM_ID, spl_token_1.TOKEN_PROGRAM_ID, new web3_js_1.PublicKey(mintAddress), new web3_js_1.PublicKey(userPubKey));
8
+ };
9
+ exports.getTokenAddress = getTokenAddress;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.2.0-master.4",
3
+ "version": "0.2.0-master.40",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -14,7 +14,11 @@
14
14
  "build": "yarn clean && tsc",
15
15
  "clean": "rm -rf lib",
16
16
  "test": "mocha -r ts-node/register tests/**/*.ts",
17
- "patch-and-pub": "npm version patch --force && npm publish"
17
+ "test:inspect": "mocha --inspect-brk -r ts-node/register tests/**/*.ts",
18
+ "test:bignum": "mocha -r ts-node/register tests/bn/**/*.ts",
19
+ "patch-and-pub": "npm version patch --force && npm publish",
20
+ "prettify": "prettier --check './src/***/*.ts'",
21
+ "prettify:fix": "prettier --write './{src,tests}/***/*.ts'"
18
22
  },
19
23
  "keywords": [
20
24
  "drift-labs",
@@ -29,11 +33,13 @@
29
33
  "access": "public"
30
34
  },
31
35
  "dependencies": {
32
- "@project-serum/anchor": "0.24.2",
36
+ "@project-serum/anchor": "0.25.0-beta.1",
37
+ "@project-serum/serum": "^0.13.38",
33
38
  "@pythnetwork/client": "2.5.3",
34
39
  "@solana/spl-token": "^0.1.6",
35
40
  "@solana/web3.js": "1.41.0",
36
41
  "@switchboard-xyz/switchboard-v2": "^0.0.67",
42
+ "async-mutex": "^0.4.0",
37
43
  "strict-event-emitter-types": "^2.0.0",
38
44
  "uuid": "^8.3.2"
39
45
  },
@@ -48,6 +54,7 @@
48
54
  "eslint-config-prettier": "^8.3.0",
49
55
  "eslint-plugin-prettier": "^3.4.0",
50
56
  "mocha": "^10.0.0",
57
+ "prettier": "^2.4.1",
51
58
  "ts-node": "^10.8.0"
52
59
  },
53
60
  "description": "SDK for Drift Protocol v1",
@@ -2,6 +2,7 @@ import { Commitment, Connection, PublicKey } from '@solana/web3.js';
2
2
  import { v4 as uuidv4 } from 'uuid';
3
3
  import { BufferAndSlot } from './types';
4
4
  import { promiseTimeout } from '../util/promiseTimeout';
5
+ import { Mutex } from 'async-mutex';
5
6
 
6
7
  type AccountToLoad = {
7
8
  publicKey: PublicKey;
@@ -22,6 +23,7 @@ export class BulkAccountLoader {
22
23
  intervalId?: NodeJS.Timer;
23
24
  // to handle clients spamming load
24
25
  loadPromise?: Promise<void>;
26
+ loadPromiseLock: Mutex = new Mutex();
25
27
  loadPromiseResolver: () => void;
26
28
  lastTimeLoadingPromiseCleared = Date.now();
27
29
  mostRecentSlot = 0;
@@ -64,7 +66,9 @@ export class BulkAccountLoader {
64
66
  }
65
67
 
66
68
  // if a new account needs to be polled, remove the cached loadPromise in case client calls load immediately after
67
- this.loadPromise = undefined;
69
+ this.loadPromiseLock.runExclusive(() => {
70
+ this.loadPromise = undefined;
71
+ });
68
72
 
69
73
  return callbackId;
70
74
  }
@@ -101,41 +105,43 @@ export class BulkAccountLoader {
101
105
  }
102
106
 
103
107
  public async load(): Promise<void> {
104
- if (this.loadPromise) {
105
- const now = Date.now();
106
- if (now - this.lastTimeLoadingPromiseCleared > oneMinute) {
107
- this.loadPromise = undefined;
108
- } else {
109
- return this.loadPromise;
108
+ await this.loadPromiseLock.runExclusive(async () => {
109
+ if (this.loadPromise) {
110
+ const now = Date.now();
111
+ if (now - this.lastTimeLoadingPromiseCleared > oneMinute) {
112
+ this.loadPromise = undefined;
113
+ } else {
114
+ return this.loadPromise;
115
+ }
110
116
  }
111
- }
112
-
113
- this.loadPromise = new Promise((resolver) => {
114
- this.loadPromiseResolver = resolver;
115
- });
116
- this.lastTimeLoadingPromiseCleared = Date.now();
117
-
118
- try {
119
- const chunks = this.chunks(
120
- Array.from(this.accountsToLoad.values()),
121
- GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE
122
- );
123
117
 
124
- await Promise.all(
125
- chunks.map((chunk) => {
126
- return this.loadChunk(chunk);
127
- })
128
- );
129
- } catch (e) {
130
- console.error(`Error in bulkAccountLoader.load()`);
131
- console.error(e);
132
- for (const [_, callback] of this.errorCallbacks) {
133
- callback(e);
118
+ this.loadPromise = new Promise((resolver) => {
119
+ this.loadPromiseResolver = resolver;
120
+ });
121
+ this.lastTimeLoadingPromiseCleared = Date.now();
122
+
123
+ try {
124
+ const chunks = this.chunks(
125
+ Array.from(this.accountsToLoad.values()),
126
+ GET_MULTIPLE_ACCOUNTS_CHUNK_SIZE
127
+ );
128
+
129
+ await Promise.all(
130
+ chunks.map((chunk) => {
131
+ return this.loadChunk(chunk);
132
+ })
133
+ );
134
+ } catch (e) {
135
+ console.error(`Error in bulkAccountLoader.load()`);
136
+ console.error(e);
137
+ for (const [_, callback] of this.errorCallbacks) {
138
+ callback(e);
139
+ }
140
+ } finally {
141
+ this.loadPromiseResolver();
142
+ this.loadPromise = undefined;
134
143
  }
135
- } finally {
136
- this.loadPromiseResolver();
137
- this.loadPromise = undefined;
138
- }
144
+ });
139
145
  }
140
146
 
141
147
  async loadChunk(accountsToLoad: AccountToLoad[]): Promise<void> {
@@ -222,7 +228,11 @@ export class BulkAccountLoader {
222
228
  return;
223
229
  }
224
230
 
225
- this.intervalId = setInterval(this.load.bind(this), this.pollingFrequency);
231
+ if (this.pollingFrequency !== 0)
232
+ this.intervalId = setInterval(
233
+ this.load.bind(this),
234
+ this.pollingFrequency
235
+ );
226
236
  }
227
237
 
228
238
  public stopPolling(): void {
@@ -0,0 +1,33 @@
1
+ import { UserStats } from '../userStats';
2
+ import { BulkAccountLoader } from './bulkAccountLoader';
3
+ import { PollingUserStatsAccountSubscriber } from './pollingUserStatsAccountSubscriber';
4
+
5
+ /**
6
+ * @param userStats
7
+ * @param accountLoader
8
+ */
9
+ export async function bulkPollingUserStatsSubscribe(
10
+ userStats: UserStats[],
11
+ accountLoader: BulkAccountLoader
12
+ ): Promise<void> {
13
+ if (userStats.length === 0) {
14
+ await accountLoader.load();
15
+ return;
16
+ }
17
+
18
+ await Promise.all(
19
+ userStats.map((userStat) => {
20
+ return (
21
+ userStat.accountSubscriber as PollingUserStatsAccountSubscriber
22
+ ).addToAccountLoader();
23
+ })
24
+ );
25
+
26
+ await accountLoader.load();
27
+
28
+ await Promise.all(
29
+ userStats.map(async (userStat) => {
30
+ return userStat.subscribe();
31
+ })
32
+ );
33
+ }
@@ -1,4 +1,4 @@
1
- import { ClearingHouseUser } from '../clearingHouseUser';
1
+ import { User } from '../user';
2
2
  import { BulkAccountLoader } from './bulkAccountLoader';
3
3
  import { PollingUserAccountSubscriber } from './pollingUserAccountSubscriber';
4
4
 
@@ -7,7 +7,7 @@ import { PollingUserAccountSubscriber } from './pollingUserAccountSubscriber';
7
7
  * @param accountLoader
8
8
  */
9
9
  export async function bulkPollingUserSubscribe(
10
- users: ClearingHouseUser[],
10
+ users: User[],
11
11
  accountLoader: BulkAccountLoader
12
12
  ): Promise<void> {
13
13
  if (users.length === 0) {
@@ -17,7 +17,6 @@ export async function bulkPollingUserSubscribe(
17
17
 
18
18
  await Promise.all(
19
19
  users.map((user) => {
20
- // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
21
20
  return (
22
21
  user.accountSubscriber as PollingUserAccountSubscriber
23
22
  ).addToAccountLoader();
@@ -1,6 +1,9 @@
1
1
  import { Connection, PublicKey } from '@solana/web3.js';
2
- import { UserAccount } from '../types';
3
- import { getUserAccountPublicKey } from '../addresses/pda';
2
+ import { UserAccount, UserStatsAccount } from '../types';
3
+ import {
4
+ getUserAccountPublicKey,
5
+ getUserStatsAccountPublicKey,
6
+ } from '../addresses/pda';
4
7
  import { Program } from '@project-serum/anchor';
5
8
 
6
9
  export async function fetchUserAccounts(
@@ -31,3 +34,25 @@ export async function fetchUserAccounts(
31
34
  ) as UserAccount;
32
35
  });
33
36
  }
37
+
38
+ export async function fetchUserStatsAccount(
39
+ connection: Connection,
40
+ program: Program,
41
+ authority: PublicKey
42
+ ): Promise<UserStatsAccount | undefined> {
43
+ const userStatsPublicKey = getUserStatsAccountPublicKey(
44
+ program.programId,
45
+ authority
46
+ );
47
+ const accountInfo = await connection.getAccountInfo(
48
+ userStatsPublicKey,
49
+ 'confirmed'
50
+ );
51
+
52
+ return accountInfo
53
+ ? (program.account.user.coder.accounts.decode(
54
+ 'UserStats',
55
+ accountInfo.data
56
+ ) as UserStatsAccount)
57
+ : undefined;
58
+ }