@drift-labs/sdk 0.1.22 → 0.1.23-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.
@@ -16,8 +16,46 @@ exports.bulkPollingUserSubscribe = void 0;
16
16
  */
17
17
  function bulkPollingUserSubscribe(users, accountLoader) {
18
18
  return __awaiter(this, void 0, void 0, function* () {
19
+ if (users.length === 0) {
20
+ yield accountLoader.load();
21
+ return;
22
+ }
23
+ // Fetch all the accounts first
24
+ const program = users[0].clearingHouse.program;
25
+ let userProgramAccounts;
26
+ let orderProgramAccounts;
27
+ yield Promise.all([
28
+ (() => __awaiter(this, void 0, void 0, function* () {
29
+ userProgramAccounts = yield program.account.user.all();
30
+ }))(),
31
+ (() => __awaiter(this, void 0, void 0, function* () {
32
+ orderProgramAccounts = yield program.account.userOrders.all();
33
+ }))(),
34
+ ]);
35
+ // Create a map of the authority to keys
36
+ const authorityToKeys = new Map();
37
+ const userToAuthority = new Map();
38
+ for (const userProgramAccount of userProgramAccounts) {
39
+ const userAccountPublicKey = userProgramAccount.publicKey;
40
+ const userAccount = userProgramAccount.account;
41
+ authorityToKeys.set(userAccount.authority.toString(), {
42
+ user: userAccountPublicKey,
43
+ userPositions: userAccount.positions,
44
+ userOrders: undefined,
45
+ });
46
+ userToAuthority.set(userAccountPublicKey.toString(), userAccount.authority.toString());
47
+ }
48
+ for (const orderProgramAccount of orderProgramAccounts) {
49
+ const userOrderAccountPublicKey = orderProgramAccount.publicKey;
50
+ const userOrderAccount = orderProgramAccount.account;
51
+ const authority = userToAuthority.get(userOrderAccount.user.toString());
52
+ const userPublicKeys = authorityToKeys.get(authority);
53
+ userPublicKeys.userOrders = userOrderAccountPublicKey;
54
+ }
19
55
  yield Promise.all(users.map((user) => {
20
- return user.accountSubscriber.addToAccountLoader();
56
+ // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
57
+ const userPublicKeys = authorityToKeys.get(user.authority.toString());
58
+ return user.accountSubscriber.addToAccountLoader(userPublicKeys);
21
59
  }));
22
60
  yield accountLoader.load();
23
61
  yield Promise.all(users.map((user) => __awaiter(this, void 0, void 0, function* () {
@@ -1,5 +1,5 @@
1
1
  /// <reference types="node" />
2
- import { AccountToPoll, UserAccountEvents, UserAccountSubscriber } from './types';
2
+ import { AccountToPoll, UserAccountEvents, UserAccountSubscriber, UserPublicKeys } from './types';
3
3
  import { Program } from '@project-serum/anchor';
4
4
  import StrictEventEmitter from 'strict-event-emitter-types';
5
5
  import { EventEmitter } from 'events';
@@ -21,7 +21,7 @@ export declare class PollingUserAccountSubscriber implements UserAccountSubscrib
21
21
  type: ClearingHouseConfigType;
22
22
  constructor(program: Program, authority: PublicKey, accountLoader: BulkAccountLoader);
23
23
  subscribe(): Promise<boolean>;
24
- addToAccountLoader(): Promise<void>;
24
+ addToAccountLoader(userPublicKeys?: UserPublicKeys): Promise<void>;
25
25
  fetchIfUnloaded(): Promise<void>;
26
26
  fetch(): Promise<void>;
27
27
  unsubscribe(): Promise<void>;
@@ -36,34 +36,55 @@ class PollingUserAccountSubscriber {
36
36
  return true;
37
37
  });
38
38
  }
39
- addToAccountLoader() {
39
+ addToAccountLoader(userPublicKeys) {
40
40
  return __awaiter(this, void 0, void 0, function* () {
41
41
  if (this.accountsToPoll.size > 0) {
42
42
  return;
43
43
  }
44
- const userPublicKey = yield addresses_1.getUserAccountPublicKey(this.program.programId, this.authority);
45
- const userAccount = (yield this.program.account.user.fetch(userPublicKey));
46
- this.accountsToPoll.set(userPublicKey.toString(), {
47
- key: 'user',
48
- publicKey: userPublicKey,
49
- eventType: 'userAccountData',
50
- });
51
- this.accountsToPoll.set(userAccount.positions.toString(), {
52
- key: 'userPositions',
53
- publicKey: userAccount.positions,
54
- eventType: 'userPositionsData',
55
- });
56
- const userOrdersPublicKey = yield addresses_1.getUserOrdersAccountPublicKey(this.program.programId, userPublicKey);
57
- const userOrdersExist = (yield this.program.provider.connection.getParsedAccountInfo(userOrdersPublicKey)).value !== null;
58
- if (userOrdersExist) {
44
+ if (!userPublicKeys) {
45
+ const userPublicKey = yield addresses_1.getUserAccountPublicKey(this.program.programId, this.authority);
46
+ const userAccount = (yield this.program.account.user.fetch(userPublicKey));
47
+ this.accountsToPoll.set(userPublicKey.toString(), {
48
+ key: 'user',
49
+ publicKey: userPublicKey,
50
+ eventType: 'userAccountData',
51
+ });
52
+ this.accountsToPoll.set(userAccount.positions.toString(), {
53
+ key: 'userPositions',
54
+ publicKey: userAccount.positions,
55
+ eventType: 'userPositionsData',
56
+ });
57
+ const userOrdersPublicKey = yield addresses_1.getUserOrdersAccountPublicKey(this.program.programId, userPublicKey);
59
58
  this.accountsToPoll.set(userOrdersPublicKey.toString(), {
60
59
  key: 'userOrders',
61
60
  publicKey: userOrdersPublicKey,
62
61
  eventType: 'userOrdersData',
63
62
  });
64
63
  }
64
+ else {
65
+ this.accountsToPoll.set(userPublicKeys.user.toString(), {
66
+ key: 'user',
67
+ publicKey: userPublicKeys.user,
68
+ eventType: 'userAccountData',
69
+ });
70
+ this.accountsToPoll.set(userPublicKeys.userPositions.toString(), {
71
+ key: 'userPositions',
72
+ publicKey: userPublicKeys.userPositions,
73
+ eventType: 'userPositionsData',
74
+ });
75
+ if (userPublicKeys.userOrders) {
76
+ this.accountsToPoll.set(userPublicKeys.userOrders.toString(), {
77
+ key: 'userOrders',
78
+ publicKey: userPublicKeys.userOrders,
79
+ eventType: 'userOrdersData',
80
+ });
81
+ }
82
+ }
65
83
  for (const [_, accountToPoll] of this.accountsToPoll) {
66
84
  accountToPoll.callbackId = this.accountLoader.addAccount(accountToPoll.publicKey, (buffer) => {
85
+ if (!buffer) {
86
+ return;
87
+ }
67
88
  const account = this.program.account[accountToPoll.key].coder.accounts.decode(utils_1.capitalize(accountToPoll.key), buffer);
68
89
  this[accountToPoll.key] = account;
69
90
  // @ts-ignore
@@ -48,6 +48,11 @@ export interface ClearingHouseAccountSubscriber {
48
48
  getOrderHistoryAccount(): OrderHistoryAccount;
49
49
  type: ClearingHouseConfigType;
50
50
  }
51
+ export declare type UserPublicKeys = {
52
+ user: PublicKey;
53
+ userPositions: PublicKey;
54
+ userOrders: PublicKey | undefined;
55
+ };
51
56
  export interface UserAccountEvents {
52
57
  userAccountData: (payload: UserAccount) => void;
53
58
  userPositionsData: (payload: UserPositionsAccount) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drift-labs/sdk",
3
- "version": "0.1.22",
3
+ "version": "0.1.23-master.0",
4
4
  "main": "lib/index.js",
5
5
  "types": "lib/index.d.ts",
6
6
  "author": "crispheaney",
@@ -1,6 +1,9 @@
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';
4
7
 
5
8
  /**
6
9
  * @param users
@@ -10,11 +13,58 @@ export async function bulkPollingUserSubscribe(
10
13
  users: ClearingHouseUser[],
11
14
  accountLoader: BulkAccountLoader
12
15
  ): Promise<void> {
16
+ if (users.length === 0) {
17
+ await accountLoader.load();
18
+ return;
19
+ }
20
+
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
+
13
61
  await Promise.all(
14
62
  users.map((user) => {
63
+ // Pull the keys from the authority map so we can skip fetching them in addToAccountLoader
64
+ const userPublicKeys = authorityToKeys.get(user.authority.toString());
15
65
  return (
16
66
  user.accountSubscriber as PollingUserAccountSubscriber
17
- ).addToAccountLoader();
67
+ ).addToAccountLoader(userPublicKeys);
18
68
  })
19
69
  );
20
70
 
@@ -3,6 +3,7 @@ import {
3
3
  NotSubscribedError,
4
4
  UserAccountEvents,
5
5
  UserAccountSubscriber,
6
+ UserPublicKeys,
6
7
  } from './types';
7
8
  import { Program } from '@project-serum/anchor';
8
9
  import StrictEventEmitter from 'strict-event-emitter-types';
@@ -58,55 +59,73 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
58
59
  return true;
59
60
  }
60
61
 
61
- async addToAccountLoader(): Promise<void> {
62
+ async addToAccountLoader(userPublicKeys?: UserPublicKeys): Promise<void> {
62
63
  if (this.accountsToPoll.size > 0) {
63
64
  return;
64
65
  }
65
66
 
66
- const userPublicKey = await getUserAccountPublicKey(
67
- this.program.programId,
68
- this.authority
69
- );
67
+ if (!userPublicKeys) {
68
+ const userPublicKey = await getUserAccountPublicKey(
69
+ this.program.programId,
70
+ this.authority
71
+ );
70
72
 
71
- const userAccount = (await this.program.account.user.fetch(
72
- userPublicKey
73
- )) as UserAccount;
73
+ const userAccount = (await this.program.account.user.fetch(
74
+ userPublicKey
75
+ )) as UserAccount;
74
76
 
75
- this.accountsToPoll.set(userPublicKey.toString(), {
76
- key: 'user',
77
- publicKey: userPublicKey,
78
- eventType: 'userAccountData',
79
- });
77
+ this.accountsToPoll.set(userPublicKey.toString(), {
78
+ key: 'user',
79
+ publicKey: userPublicKey,
80
+ eventType: 'userAccountData',
81
+ });
80
82
 
81
- this.accountsToPoll.set(userAccount.positions.toString(), {
82
- key: 'userPositions',
83
- publicKey: userAccount.positions,
84
- eventType: 'userPositionsData',
85
- });
83
+ this.accountsToPoll.set(userAccount.positions.toString(), {
84
+ key: 'userPositions',
85
+ publicKey: userAccount.positions,
86
+ eventType: 'userPositionsData',
87
+ });
88
+
89
+ const userOrdersPublicKey = await getUserOrdersAccountPublicKey(
90
+ this.program.programId,
91
+ userPublicKey
92
+ );
86
93
 
87
- const userOrdersPublicKey = await getUserOrdersAccountPublicKey(
88
- this.program.programId,
89
- userPublicKey
90
- );
91
-
92
- const userOrdersExist =
93
- (
94
- await this.program.provider.connection.getParsedAccountInfo(
95
- userOrdersPublicKey
96
- )
97
- ).value !== null;
98
- if (userOrdersExist) {
99
94
  this.accountsToPoll.set(userOrdersPublicKey.toString(), {
100
95
  key: 'userOrders',
101
96
  publicKey: userOrdersPublicKey,
102
97
  eventType: 'userOrdersData',
103
98
  });
99
+ } else {
100
+ this.accountsToPoll.set(userPublicKeys.user.toString(), {
101
+ key: 'user',
102
+ publicKey: userPublicKeys.user,
103
+ eventType: 'userAccountData',
104
+ });
105
+
106
+ this.accountsToPoll.set(userPublicKeys.userPositions.toString(), {
107
+ key: 'userPositions',
108
+ publicKey: userPublicKeys.userPositions,
109
+ eventType: 'userPositionsData',
110
+ });
111
+
112
+ if (userPublicKeys.userOrders) {
113
+ this.accountsToPoll.set(userPublicKeys.userOrders.toString(), {
114
+ key: 'userOrders',
115
+ publicKey: userPublicKeys.userOrders,
116
+ eventType: 'userOrdersData',
117
+ });
118
+ }
104
119
  }
105
120
 
106
121
  for (const [_, accountToPoll] of this.accountsToPoll) {
107
122
  accountToPoll.callbackId = this.accountLoader.addAccount(
108
123
  accountToPoll.publicKey,
109
124
  (buffer) => {
125
+ if (!buffer) {
126
+ return;
127
+ }
128
+
110
129
  const account = this.program.account[
111
130
  accountToPoll.key
112
131
  ].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
@@ -82,6 +82,12 @@ export interface ClearingHouseAccountSubscriber {
82
82
  type: ClearingHouseConfigType;
83
83
  }
84
84
 
85
+ export type UserPublicKeys = {
86
+ user: PublicKey;
87
+ userPositions: PublicKey;
88
+ userOrders: PublicKey | undefined;
89
+ };
90
+
85
91
  export interface UserAccountEvents {
86
92
  userAccountData: (payload: UserAccount) => void;
87
93
  userPositionsData: (payload: UserPositionsAccount) => void;