@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.
- package/lib/accounts/bulkUserSubscription.js +39 -1
- package/lib/accounts/pollingUserAccountSubscriber.d.ts +2 -2
- package/lib/accounts/pollingUserAccountSubscriber.js +37 -16
- package/lib/accounts/types.d.ts +5 -0
- package/package.json +1 -1
- package/src/accounts/bulkUserSubscription.ts +51 -1
- package/src/accounts/pollingUserAccountSubscriber.ts +49 -30
- package/src/accounts/types.ts +6 -0
|
@@ -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
|
-
|
|
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
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
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
|
package/lib/accounts/types.d.ts
CHANGED
|
@@ -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,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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
if (!userPublicKeys) {
|
|
68
|
+
const userPublicKey = await getUserAccountPublicKey(
|
|
69
|
+
this.program.programId,
|
|
70
|
+
this.authority
|
|
71
|
+
);
|
|
70
72
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
73
|
+
const userAccount = (await this.program.account.user.fetch(
|
|
74
|
+
userPublicKey
|
|
75
|
+
)) as UserAccount;
|
|
74
76
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
77
|
+
this.accountsToPoll.set(userPublicKey.toString(), {
|
|
78
|
+
key: 'user',
|
|
79
|
+
publicKey: userPublicKey,
|
|
80
|
+
eventType: 'userAccountData',
|
|
81
|
+
});
|
|
80
82
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
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);
|
package/src/accounts/types.ts
CHANGED
|
@@ -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;
|