@drift-labs/sdk 2.25.4 → 2.26.0-beta.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/pollingUserAccountSubscriber.d.ts +5 -4
- package/lib/accounts/pollingUserAccountSubscriber.js +35 -48
- package/lib/accounts/pollingUserStatsAccountSubscriber.d.ts +4 -4
- package/lib/accounts/pollingUserStatsAccountSubscriber.js +30 -47
- package/lib/accounts/types.d.ts +2 -1
- package/lib/accounts/webSocketAccountSubscriber.d.ts +1 -1
- package/lib/accounts/webSocketAccountSubscriber.js +4 -3
- package/lib/accounts/webSocketUserAccountSubscriber.d.ts +1 -0
- package/lib/accounts/webSocketUserAccountSubscriber.js +9 -0
- package/lib/addresses/pda.d.ts +2 -0
- package/lib/addresses/pda.js +8 -1
- package/lib/adminClient.d.ts +2 -0
- package/lib/adminClient.js +20 -0
- package/lib/constants/numericConstants.d.ts +61 -59
- package/lib/constants/spotMarkets.d.ts +1 -0
- package/lib/dlob/DLOB.d.ts +1 -0
- package/lib/dlob/DLOBApiClient.d.ts +14 -0
- package/lib/dlob/DLOBApiClient.js +34 -0
- package/lib/dlob/DLOBNode.d.ts +1 -0
- package/lib/dlob/DLOBSubscriber.d.ts +19 -0
- package/lib/dlob/DLOBSubscriber.js +42 -0
- package/lib/dlob/NodeList.d.ts +1 -0
- package/lib/dlob/types.d.ts +16 -0
- package/lib/dlob/types.js +2 -0
- package/lib/driftClient.d.ts +14 -10
- package/lib/driftClient.js +124 -28
- package/lib/examples/loadDlob.js +2 -4
- package/lib/factory/bigNum.d.ts +8 -7
- package/lib/idl/drift.json +264 -82
- package/lib/index.d.ts +2 -0
- package/lib/index.js +2 -0
- package/lib/math/amm.d.ts +2 -1
- package/lib/math/auction.d.ts +1 -0
- package/lib/math/conversion.d.ts +2 -1
- package/lib/math/funding.d.ts +1 -0
- package/lib/math/insurance.d.ts +1 -0
- package/lib/math/margin.d.ts +1 -0
- package/lib/math/market.d.ts +1 -0
- package/lib/math/oracles.d.ts +1 -0
- package/lib/math/orders.d.ts +1 -0
- package/lib/math/position.d.ts +1 -0
- package/lib/math/repeg.d.ts +1 -0
- package/lib/math/spotBalance.d.ts +1 -0
- package/lib/math/spotMarket.d.ts +1 -0
- package/lib/math/spotPosition.d.ts +1 -0
- package/lib/math/trade.d.ts +1 -0
- package/lib/math/utils.d.ts +1 -0
- package/lib/oracles/pythClient.d.ts +2 -1
- package/lib/oracles/types.d.ts +1 -0
- package/lib/orderParams.d.ts +1 -0
- package/lib/serum/serumSubscriber.d.ts +1 -0
- package/lib/slot/SlotSubscriber.js +3 -0
- package/lib/tokenFaucet.d.ts +1 -0
- package/lib/tx/retryTxSender.d.ts +2 -1
- package/lib/tx/retryTxSender.js +5 -1
- package/lib/tx/types.d.ts +4 -1
- package/lib/types.d.ts +12 -0
- package/lib/user.d.ts +1 -0
- package/lib/userMap/userMap.d.ts +17 -6
- package/lib/userMap/userMap.js +74 -46
- package/lib/userMap/userStatsMap.d.ts +6 -3
- package/lib/userMap/userStatsMap.js +30 -30
- package/package.json +2 -1
- package/src/accounts/pollingUserAccountSubscriber.ts +51 -63
- package/src/accounts/pollingUserStatsAccountSubscriber.ts +46 -62
- package/src/accounts/types.ts +2 -1
- package/src/accounts/webSocketAccountSubscriber.ts +4 -3
- package/src/accounts/webSocketUserAccountSubscriber.ts +10 -0
- package/src/addresses/pda.ts +13 -0
- package/src/adminClient.ts +34 -0
- package/src/dlob/DLOBApiClient.ts +37 -0
- package/src/dlob/DLOBSubscriber.ts +57 -0
- package/src/dlob/types.ts +20 -0
- package/src/driftClient.ts +216 -59
- package/src/examples/loadDlob.ts +2 -4
- package/src/idl/drift.json +264 -82
- package/src/index.ts +2 -0
- package/src/slot/SlotSubscriber.ts +4 -0
- package/src/tx/retryTxSender.ts +19 -2
- package/src/tx/types.ts +13 -0
- package/src/types.ts +12 -0
- package/src/userMap/userMap.ts +111 -60
- package/src/userMap/userStatsMap.ts +43 -44
- package/tests/dlob/helpers.ts +3 -1
- package/src/assert/assert.js +0 -9
- package/src/token/index.js +0 -38
- package/src/util/computeUnits.js +0 -27
- package/src/util/getTokenAddress.js +0 -9
- package/src/util/promiseTimeout.js +0 -14
- package/src/util/tps.js +0 -27
package/lib/userMap/userMap.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { User, DriftClient, OrderRecord, UserSubscriptionConfig, WrappedEvent } from '..';
|
|
1
|
+
import { User, DriftClient, UserAccount, OrderRecord, UserSubscriptionConfig, WrappedEvent, DLOB } from '..';
|
|
2
2
|
import { PublicKey } from '@solana/web3.js';
|
|
3
3
|
export interface UserMapInterface {
|
|
4
|
-
|
|
4
|
+
subscribe(): Promise<void>;
|
|
5
|
+
unsubscribe(): Promise<void>;
|
|
5
6
|
addPubkey(userAccountPublicKey: PublicKey): Promise<void>;
|
|
6
7
|
has(key: string): boolean;
|
|
7
8
|
get(key: string): User | undefined;
|
|
@@ -14,9 +15,12 @@ export declare class UserMap implements UserMapInterface {
|
|
|
14
15
|
private userMap;
|
|
15
16
|
private driftClient;
|
|
16
17
|
private accountSubscription;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
private includeIdle;
|
|
19
|
+
private lastNumberOfSubAccounts;
|
|
20
|
+
private syncCallback;
|
|
21
|
+
constructor(driftClient: DriftClient, accountSubscription: UserSubscriptionConfig, includeIdle?: boolean);
|
|
22
|
+
subscribe(): Promise<void>;
|
|
23
|
+
addPubkey(userAccountPublicKey: PublicKey, userAccount?: UserAccount): Promise<void>;
|
|
20
24
|
has(key: string): boolean;
|
|
21
25
|
/**
|
|
22
26
|
* gets the User for a particular userAccountPublicKey, if no User exists, undefined is returned
|
|
@@ -36,9 +40,16 @@ export declare class UserMap implements UserMapInterface {
|
|
|
36
40
|
* @returns authority PublicKey | undefined
|
|
37
41
|
*/
|
|
38
42
|
getUserAuthority(key: string): PublicKey | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* implements the {@link DLOBSource} interface
|
|
45
|
+
* create a DLOB from all the subscribed users
|
|
46
|
+
* @param slot
|
|
47
|
+
*/
|
|
48
|
+
getDLOB(slot: number): Promise<DLOB>;
|
|
39
49
|
updateWithOrderRecord(record: OrderRecord): Promise<void>;
|
|
40
50
|
updateWithEventRecord(record: WrappedEvent<any>): Promise<void>;
|
|
41
51
|
values(): IterableIterator<User>;
|
|
42
52
|
size(): number;
|
|
43
|
-
sync(
|
|
53
|
+
sync(): Promise<void>;
|
|
54
|
+
unsubscribe(): Promise<void>;
|
|
44
55
|
}
|
package/lib/userMap/userMap.js
CHANGED
|
@@ -6,46 +6,38 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.UserMap = void 0;
|
|
7
7
|
const __1 = require("..");
|
|
8
8
|
const web3_js_1 = require("@solana/web3.js");
|
|
9
|
+
const buffer_1 = require("buffer");
|
|
9
10
|
const bs58_1 = __importDefault(require("bs58"));
|
|
10
11
|
class UserMap {
|
|
11
|
-
constructor(driftClient, accountSubscription) {
|
|
12
|
+
constructor(driftClient, accountSubscription, includeIdle = true) {
|
|
12
13
|
this.userMap = new Map();
|
|
14
|
+
this.syncCallback = async (state) => {
|
|
15
|
+
if (state.numberOfSubAccounts !== this.lastNumberOfSubAccounts) {
|
|
16
|
+
await this.sync();
|
|
17
|
+
this.lastNumberOfSubAccounts = state.numberOfSubAccounts;
|
|
18
|
+
}
|
|
19
|
+
};
|
|
13
20
|
this.driftClient = driftClient;
|
|
14
21
|
this.accountSubscription = accountSubscription;
|
|
22
|
+
this.includeIdle = includeIdle;
|
|
15
23
|
}
|
|
16
|
-
async
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
driftClient: this.driftClient,
|
|
26
|
-
userAccountPublicKey: programUserAccount.publicKey,
|
|
27
|
-
accountSubscription: this.accountSubscription,
|
|
28
|
-
});
|
|
29
|
-
userArray.push(user);
|
|
30
|
-
userAccountArray.push(programUserAccount.account);
|
|
31
|
-
}
|
|
32
|
-
if (this.accountSubscription.type === 'polling') {
|
|
33
|
-
await (0, __1.bulkPollingUserSubscribe)(userArray, this.accountSubscription.accountLoader);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
await Promise.all(userArray.map((user, i) => user.subscribe(userAccountArray[i])));
|
|
37
|
-
}
|
|
38
|
-
for (const user of userArray) {
|
|
39
|
-
this.userMap.set(user.getUserAccountPublicKey().toString(), user);
|
|
40
|
-
}
|
|
24
|
+
async subscribe() {
|
|
25
|
+
if (this.size() > 0) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
await this.driftClient.subscribe();
|
|
29
|
+
this.lastNumberOfSubAccounts =
|
|
30
|
+
this.driftClient.getStateAccount().numberOfSubAccounts;
|
|
31
|
+
this.driftClient.eventEmitter.on('stateAccountUpdate', this.syncCallback);
|
|
32
|
+
await this.sync();
|
|
41
33
|
}
|
|
42
|
-
async addPubkey(userAccountPublicKey) {
|
|
34
|
+
async addPubkey(userAccountPublicKey, userAccount) {
|
|
43
35
|
const user = new __1.User({
|
|
44
36
|
driftClient: this.driftClient,
|
|
45
37
|
userAccountPublicKey,
|
|
46
38
|
accountSubscription: this.accountSubscription,
|
|
47
39
|
});
|
|
48
|
-
await user.subscribe();
|
|
40
|
+
await user.subscribe(userAccount);
|
|
49
41
|
this.userMap.set(userAccountPublicKey.toString(), user);
|
|
50
42
|
}
|
|
51
43
|
has(key) {
|
|
@@ -83,6 +75,16 @@ class UserMap {
|
|
|
83
75
|
}
|
|
84
76
|
return chUser.getUserAccount().authority;
|
|
85
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* implements the {@link DLOBSource} interface
|
|
80
|
+
* create a DLOB from all the subscribed users
|
|
81
|
+
* @param slot
|
|
82
|
+
*/
|
|
83
|
+
async getDLOB(slot) {
|
|
84
|
+
const dlob = new __1.DLOB();
|
|
85
|
+
await dlob.initFromUserMap(this, slot);
|
|
86
|
+
return dlob;
|
|
87
|
+
}
|
|
86
88
|
async updateWithOrderRecord(record) {
|
|
87
89
|
if (!this.has(record.user.toString())) {
|
|
88
90
|
await this.addPubkey(record.user);
|
|
@@ -134,9 +136,9 @@ class UserMap {
|
|
|
134
136
|
size() {
|
|
135
137
|
return this.userMap.size;
|
|
136
138
|
}
|
|
137
|
-
async sync(
|
|
139
|
+
async sync() {
|
|
138
140
|
let filters = undefined;
|
|
139
|
-
if (!includeIdle) {
|
|
141
|
+
if (!this.includeIdle) {
|
|
140
142
|
filters = [
|
|
141
143
|
{
|
|
142
144
|
memcmp: {
|
|
@@ -146,29 +148,55 @@ class UserMap {
|
|
|
146
148
|
},
|
|
147
149
|
];
|
|
148
150
|
}
|
|
149
|
-
const
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
151
|
+
const rpcRequestArgs = [
|
|
152
|
+
this.driftClient.program.programId.toBase58(),
|
|
153
|
+
{
|
|
154
|
+
commitment: this.driftClient.connection.commitment,
|
|
155
|
+
filters: [
|
|
156
|
+
{
|
|
157
|
+
memcmp: this.driftClient.program.coder.accounts.memcmp('User'),
|
|
158
|
+
},
|
|
159
|
+
...(Array.isArray(filters) ? filters : []),
|
|
160
|
+
],
|
|
161
|
+
encoding: 'base64',
|
|
162
|
+
withContext: true,
|
|
163
|
+
},
|
|
164
|
+
];
|
|
165
|
+
// @ts-ignore
|
|
166
|
+
const rpcJSONResponse = await this.driftClient.connection._rpcRequest('getProgramAccounts', rpcRequestArgs);
|
|
167
|
+
const rpcResponseAndContext = rpcJSONResponse.result;
|
|
168
|
+
const slot = rpcResponseAndContext.context.slot;
|
|
169
|
+
const programAccountBufferMap = new Map();
|
|
170
|
+
for (const programAccount of rpcResponseAndContext.value) {
|
|
171
|
+
programAccountBufferMap.set(programAccount.pubkey.toString(),
|
|
172
|
+
// @ts-ignore
|
|
173
|
+
buffer_1.Buffer.from(programAccount.account.data[0], programAccount.account.data[1]));
|
|
174
|
+
}
|
|
175
|
+
for (const [key, buffer] of programAccountBufferMap.entries()) {
|
|
163
176
|
if (!this.has(key)) {
|
|
164
|
-
|
|
177
|
+
const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', buffer);
|
|
178
|
+
await this.addPubkey(new web3_js_1.PublicKey(key), userAccount);
|
|
165
179
|
}
|
|
166
180
|
}
|
|
167
181
|
for (const [key, user] of this.userMap.entries()) {
|
|
168
|
-
if (!
|
|
182
|
+
if (!programAccountBufferMap.has(key)) {
|
|
169
183
|
await user.unsubscribe();
|
|
170
184
|
this.userMap.delete(key);
|
|
171
185
|
}
|
|
186
|
+
else {
|
|
187
|
+
const userAccount = this.driftClient.program.account.user.coder.accounts.decode('User', programAccountBufferMap.get(key));
|
|
188
|
+
user.accountSubscriber.updateData(userAccount, slot);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
async unsubscribe() {
|
|
193
|
+
for (const [key, user] of this.userMap.entries()) {
|
|
194
|
+
await user.unsubscribe();
|
|
195
|
+
this.userMap.delete(key);
|
|
196
|
+
}
|
|
197
|
+
if (this.lastNumberOfSubAccounts) {
|
|
198
|
+
this.driftClient.eventEmitter.removeListener('stateAccountUpdate', this.syncCallback);
|
|
199
|
+
this.lastNumberOfSubAccounts = undefined;
|
|
172
200
|
}
|
|
173
201
|
}
|
|
174
202
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { DriftClient, OrderRecord, UserStats, UserStatsSubscriptionConfig, WrappedEvent } from '..';
|
|
1
|
+
import { DriftClient, OrderRecord, UserStatsAccount, UserStats, UserStatsSubscriptionConfig, WrappedEvent } from '..';
|
|
2
2
|
import { PublicKey } from '@solana/web3.js';
|
|
3
3
|
import { UserMap } from './userMap';
|
|
4
4
|
export declare class UserStatsMap {
|
|
@@ -8,9 +8,11 @@ export declare class UserStatsMap {
|
|
|
8
8
|
private userStatsMap;
|
|
9
9
|
private driftClient;
|
|
10
10
|
private accountSubscription;
|
|
11
|
+
private lastNumberOfAuthorities;
|
|
12
|
+
private syncCallback;
|
|
11
13
|
constructor(driftClient: DriftClient, accountSubscription: UserStatsSubscriptionConfig);
|
|
12
|
-
|
|
13
|
-
addUserStat(authority: PublicKey): Promise<void>;
|
|
14
|
+
subscribe(): Promise<void>;
|
|
15
|
+
addUserStat(authority: PublicKey, userStatsAccount?: UserStatsAccount): Promise<void>;
|
|
14
16
|
updateWithOrderRecord(record: OrderRecord, userMap: UserMap): Promise<void>;
|
|
15
17
|
updateWithEventRecord(record: WrappedEvent<any>, userMap?: UserMap): Promise<void>;
|
|
16
18
|
has(authorityPublicKey: string): boolean;
|
|
@@ -19,4 +21,5 @@ export declare class UserStatsMap {
|
|
|
19
21
|
values(): IterableIterator<UserStats>;
|
|
20
22
|
size(): number;
|
|
21
23
|
sync(): Promise<void>;
|
|
24
|
+
unsubscribe(): Promise<void>;
|
|
22
25
|
}
|
|
@@ -9,49 +9,38 @@ class UserStatsMap {
|
|
|
9
9
|
* map from authority pubkey to UserStats
|
|
10
10
|
*/
|
|
11
11
|
this.userStatsMap = new Map();
|
|
12
|
+
this.syncCallback = async (state) => {
|
|
13
|
+
if (state.numberOfAuthorities !== this.lastNumberOfAuthorities) {
|
|
14
|
+
await this.sync();
|
|
15
|
+
this.lastNumberOfAuthorities = state.numberOfAuthorities;
|
|
16
|
+
}
|
|
17
|
+
};
|
|
12
18
|
this.driftClient = driftClient;
|
|
13
19
|
this.accountSubscription = accountSubscription;
|
|
14
20
|
}
|
|
15
|
-
async
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const chUserStat = new __1.UserStats({
|
|
25
|
-
driftClient: this.driftClient,
|
|
26
|
-
userStatsAccountPublicKey: programUserAccount.publicKey,
|
|
27
|
-
accountSubscription: this.accountSubscription,
|
|
28
|
-
});
|
|
29
|
-
userStatArray.push(chUserStat);
|
|
30
|
-
userStatsAccountArray.push(userStat);
|
|
31
|
-
}
|
|
32
|
-
if (this.accountSubscription.type === 'polling') {
|
|
33
|
-
await (0, __1.bulkPollingUserStatsSubscribe)(userStatArray, this.accountSubscription.accountLoader);
|
|
34
|
-
}
|
|
35
|
-
else {
|
|
36
|
-
await Promise.all(userStatArray.map((userStat, i) => userStat.subscribe(userStatsAccountArray[i])));
|
|
37
|
-
}
|
|
38
|
-
for (const userStat of userStatArray) {
|
|
39
|
-
this.userStatsMap.set(userStat.getAccount().authority.toString(), userStat);
|
|
40
|
-
}
|
|
21
|
+
async subscribe() {
|
|
22
|
+
if (this.size() > 0) {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
await this.driftClient.subscribe();
|
|
26
|
+
this.lastNumberOfAuthorities =
|
|
27
|
+
this.driftClient.getStateAccount().numberOfAuthorities;
|
|
28
|
+
this.driftClient.eventEmitter.on('stateAccountUpdate', this.syncCallback);
|
|
29
|
+
await this.sync();
|
|
41
30
|
}
|
|
42
|
-
async addUserStat(authority) {
|
|
31
|
+
async addUserStat(authority, userStatsAccount) {
|
|
43
32
|
const userStat = new __1.UserStats({
|
|
44
33
|
driftClient: this.driftClient,
|
|
45
34
|
userStatsAccountPublicKey: (0, __1.getUserStatsAccountPublicKey)(this.driftClient.program.programId, authority),
|
|
46
35
|
accountSubscription: this.accountSubscription,
|
|
47
36
|
});
|
|
48
|
-
await userStat.subscribe();
|
|
37
|
+
await userStat.subscribe(userStatsAccount);
|
|
49
38
|
this.userStatsMap.set(authority.toString(), userStat);
|
|
50
39
|
}
|
|
51
40
|
async updateWithOrderRecord(record, userMap) {
|
|
52
41
|
const user = await userMap.mustGet(record.user.toString());
|
|
53
42
|
if (!this.has(user.getUserAccount().authority.toString())) {
|
|
54
|
-
this.addUserStat(user.getUserAccount().authority);
|
|
43
|
+
await this.addUserStat(user.getUserAccount().authority);
|
|
55
44
|
}
|
|
56
45
|
}
|
|
57
46
|
async updateWithEventRecord(record, userMap) {
|
|
@@ -152,9 +141,20 @@ class UserStatsMap {
|
|
|
152
141
|
}
|
|
153
142
|
for (const key of programAccountMap.keys()) {
|
|
154
143
|
if (!this.has(key)) {
|
|
155
|
-
|
|
144
|
+
const userStatsAccount = this.driftClient.program.account.userStats.coder.accounts.decode('UserStats', programAccountMap.get(key).data);
|
|
145
|
+
await this.addUserStat(new web3_js_1.PublicKey(key), userStatsAccount);
|
|
156
146
|
}
|
|
157
147
|
}
|
|
158
148
|
}
|
|
149
|
+
async unsubscribe() {
|
|
150
|
+
for (const [key, userStats] of this.userStatsMap.entries()) {
|
|
151
|
+
await userStats.unsubscribe();
|
|
152
|
+
this.userStatsMap.delete(key);
|
|
153
|
+
}
|
|
154
|
+
if (this.lastNumberOfAuthorities) {
|
|
155
|
+
this.driftClient.eventEmitter.removeListener('stateAccountUpdate', this.syncCallback);
|
|
156
|
+
this.lastNumberOfAuthorities = undefined;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
159
|
}
|
|
160
160
|
exports.UserStatsMap = UserStatsMap;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@drift-labs/sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.26.0-beta.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "lib/index.d.ts",
|
|
6
6
|
"author": "crispheaney",
|
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@coral-xyz/anchor": "0.26.0",
|
|
37
|
+
"@ellipsis-labs/phoenix-sdk": "^1.3.2",
|
|
37
38
|
"@project-serum/serum": "^0.13.38",
|
|
38
39
|
"@pythnetwork/client": "2.5.3",
|
|
39
40
|
"@solana/spl-token": "^0.1.6",
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DataAndSlot,
|
|
3
|
-
AccountToPoll,
|
|
4
3
|
NotSubscribedError,
|
|
5
4
|
UserAccountEvents,
|
|
6
5
|
UserAccountSubscriber,
|
|
@@ -11,7 +10,6 @@ import { EventEmitter } from 'events';
|
|
|
11
10
|
import { PublicKey } from '@solana/web3.js';
|
|
12
11
|
import { UserAccount } from '../types';
|
|
13
12
|
import { BulkAccountLoader } from './bulkAccountLoader';
|
|
14
|
-
import { capitalize } from './utils';
|
|
15
13
|
|
|
16
14
|
export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
17
15
|
isSubscribed: boolean;
|
|
@@ -20,7 +18,7 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
20
18
|
userAccountPublicKey: PublicKey;
|
|
21
19
|
|
|
22
20
|
accountLoader: BulkAccountLoader;
|
|
23
|
-
|
|
21
|
+
callbackId?: string;
|
|
24
22
|
errorCallbackId?: string;
|
|
25
23
|
|
|
26
24
|
user?: DataAndSlot<UserAccount>;
|
|
@@ -37,15 +35,19 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
37
35
|
this.userAccountPublicKey = userAccountPublicKey;
|
|
38
36
|
}
|
|
39
37
|
|
|
40
|
-
async subscribe(): Promise<boolean> {
|
|
38
|
+
async subscribe(userAccount?: UserAccount): Promise<boolean> {
|
|
41
39
|
if (this.isSubscribed) {
|
|
42
40
|
return true;
|
|
43
41
|
}
|
|
44
42
|
|
|
43
|
+
if (userAccount) {
|
|
44
|
+
this.user = { data: userAccount, slot: undefined };
|
|
45
|
+
}
|
|
46
|
+
|
|
45
47
|
await this.addToAccountLoader();
|
|
46
48
|
|
|
47
49
|
await this.fetchIfUnloaded();
|
|
48
|
-
if (this.
|
|
50
|
+
if (this.doesAccountExist()) {
|
|
49
51
|
this.eventEmitter.emit('update');
|
|
50
52
|
}
|
|
51
53
|
|
|
@@ -54,34 +56,30 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
54
56
|
}
|
|
55
57
|
|
|
56
58
|
async addToAccountLoader(): Promise<void> {
|
|
57
|
-
if (this.
|
|
59
|
+
if (this.callbackId) {
|
|
58
60
|
return;
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
this.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
63
|
+
this.callbackId = await this.accountLoader.addAccount(
|
|
64
|
+
this.userAccountPublicKey,
|
|
65
|
+
(buffer, slot: number) => {
|
|
66
|
+
if (!buffer) {
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
66
69
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
accountToPoll.publicKey,
|
|
70
|
-
(buffer, slot) => {
|
|
71
|
-
if (!buffer) {
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const account = this.program.account[
|
|
76
|
-
accountToPoll.key
|
|
77
|
-
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
78
|
-
this[accountToPoll.key] = { data: account, slot };
|
|
79
|
-
// @ts-ignore
|
|
80
|
-
this.eventEmitter.emit(accountToPoll.eventType, account);
|
|
81
|
-
this.eventEmitter.emit('update');
|
|
70
|
+
if (this.user && this.user.slot > slot) {
|
|
71
|
+
return;
|
|
82
72
|
}
|
|
83
|
-
|
|
84
|
-
|
|
73
|
+
|
|
74
|
+
const account = this.program.account.user.coder.accounts.decode(
|
|
75
|
+
'User',
|
|
76
|
+
buffer
|
|
77
|
+
);
|
|
78
|
+
this.user = { data: account, slot };
|
|
79
|
+
this.eventEmitter.emit('userAccountUpdate', account);
|
|
80
|
+
this.eventEmitter.emit('update');
|
|
81
|
+
}
|
|
82
|
+
);
|
|
85
83
|
|
|
86
84
|
this.errorCallbackId = this.accountLoader.addErrorCallbacks((error) => {
|
|
87
85
|
this.eventEmitter.emit('error', error);
|
|
@@ -89,43 +87,28 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
async fetchIfUnloaded(): Promise<void> {
|
|
92
|
-
|
|
93
|
-
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
94
|
-
if (this[accountToPoll.key] === undefined) {
|
|
95
|
-
shouldFetch = true;
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
if (shouldFetch) {
|
|
90
|
+
if (this.user === undefined) {
|
|
101
91
|
await this.fetch();
|
|
102
92
|
}
|
|
103
93
|
}
|
|
104
94
|
|
|
105
95
|
async fetch(): Promise<void> {
|
|
106
96
|
await this.accountLoader.load();
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
97
|
+
const { buffer, slot } = this.accountLoader.getBufferAndSlot(
|
|
98
|
+
this.userAccountPublicKey
|
|
99
|
+
);
|
|
100
|
+
const currentSlot = this.user?.slot ?? 0;
|
|
101
|
+
if (buffer && slot > currentSlot) {
|
|
102
|
+
const account = this.program.account.user.coder.accounts.decode(
|
|
103
|
+
'User',
|
|
104
|
+
buffer
|
|
110
105
|
);
|
|
111
|
-
|
|
112
|
-
const account = this.program.account[
|
|
113
|
-
accountToPoll.key
|
|
114
|
-
].coder.accounts.decode(capitalize(accountToPoll.key), buffer);
|
|
115
|
-
this[accountToPoll.key] = { data: account, slot };
|
|
116
|
-
}
|
|
106
|
+
this.user = { data: account, slot };
|
|
117
107
|
}
|
|
118
108
|
}
|
|
119
109
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
for (const [_, accountToPoll] of this.accountsToPoll) {
|
|
123
|
-
if (!this[accountToPoll.key]) {
|
|
124
|
-
success = false;
|
|
125
|
-
break;
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
return success;
|
|
110
|
+
doesAccountExist(): boolean {
|
|
111
|
+
return this.user !== undefined;
|
|
129
112
|
}
|
|
130
113
|
|
|
131
114
|
async unsubscribe(): Promise<void> {
|
|
@@ -133,18 +116,15 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
133
116
|
return;
|
|
134
117
|
}
|
|
135
118
|
|
|
136
|
-
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
119
|
+
this.accountLoader.removeAccount(
|
|
120
|
+
this.userAccountPublicKey,
|
|
121
|
+
this.callbackId
|
|
122
|
+
);
|
|
123
|
+
this.callbackId = undefined;
|
|
142
124
|
|
|
143
125
|
this.accountLoader.removeErrorCallbacks(this.errorCallbackId);
|
|
144
126
|
this.errorCallbackId = undefined;
|
|
145
127
|
|
|
146
|
-
this.accountsToPoll.clear();
|
|
147
|
-
|
|
148
128
|
this.isSubscribed = false;
|
|
149
129
|
}
|
|
150
130
|
|
|
@@ -160,4 +140,12 @@ export class PollingUserAccountSubscriber implements UserAccountSubscriber {
|
|
|
160
140
|
this.assertIsSubscribed();
|
|
161
141
|
return this.user;
|
|
162
142
|
}
|
|
143
|
+
|
|
144
|
+
public updateData(userAccount: UserAccount, slot: number): void {
|
|
145
|
+
if (!this.user || this.user.slot < slot) {
|
|
146
|
+
this.user = { data: userAccount, slot };
|
|
147
|
+
this.eventEmitter.emit('userAccountUpdate', userAccount);
|
|
148
|
+
this.eventEmitter.emit('update');
|
|
149
|
+
}
|
|
150
|
+
}
|
|
163
151
|
}
|