@account-kit/signer 4.0.0-alpha.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/LICENSE +21 -0
- package/dist/cjs/base.d.ts +37 -0
- package/dist/cjs/base.js +292 -0
- package/dist/cjs/base.js.map +1 -0
- package/dist/cjs/client/base.d.ts +230 -0
- package/dist/cjs/client/base.js +298 -0
- package/dist/cjs/client/base.js.map +1 -0
- package/dist/cjs/client/index.d.ts +146 -0
- package/dist/cjs/client/index.js +260 -0
- package/dist/cjs/client/index.js.map +1 -0
- package/dist/cjs/client/types.d.ts +106 -0
- package/dist/cjs/client/types.js +3 -0
- package/dist/cjs/client/types.js.map +1 -0
- package/dist/cjs/errors.d.ts +4 -0
- package/dist/cjs/errors.js +16 -0
- package/dist/cjs/errors.js.map +1 -0
- package/dist/cjs/index.d.ts +8 -0
- package/dist/cjs/index.js +14 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/session/manager.d.ts +45 -0
- package/dist/cjs/session/manager.js +230 -0
- package/dist/cjs/session/manager.js.map +1 -0
- package/dist/cjs/session/types.d.ts +16 -0
- package/dist/cjs/session/types.js +3 -0
- package/dist/cjs/session/types.js.map +1 -0
- package/dist/cjs/signer.d.ts +262 -0
- package/dist/cjs/signer.js +34 -0
- package/dist/cjs/signer.js.map +1 -0
- package/dist/cjs/types.d.ts +14 -0
- package/dist/cjs/types.js +12 -0
- package/dist/cjs/types.js.map +1 -0
- package/dist/cjs/utils/base64UrlEncode.d.ts +1 -0
- package/dist/cjs/utils/base64UrlEncode.js +12 -0
- package/dist/cjs/utils/base64UrlEncode.js.map +1 -0
- package/dist/cjs/utils/generateRandomBuffer.d.ts +1 -0
- package/dist/cjs/utils/generateRandomBuffer.js +10 -0
- package/dist/cjs/utils/generateRandomBuffer.js.map +1 -0
- package/dist/cjs/version.d.ts +1 -0
- package/dist/cjs/version.js +5 -0
- package/dist/cjs/version.js.map +1 -0
- package/dist/esm/base.d.ts +37 -0
- package/dist/esm/base.js +288 -0
- package/dist/esm/base.js.map +1 -0
- package/dist/esm/client/base.d.ts +230 -0
- package/dist/esm/client/base.js +291 -0
- package/dist/esm/client/base.js.map +1 -0
- package/dist/esm/client/index.d.ts +146 -0
- package/dist/esm/client/index.js +256 -0
- package/dist/esm/client/index.js.map +1 -0
- package/dist/esm/client/types.d.ts +106 -0
- package/dist/esm/client/types.js +2 -0
- package/dist/esm/client/types.js.map +1 -0
- package/dist/esm/errors.d.ts +4 -0
- package/dist/esm/errors.js +12 -0
- package/dist/esm/errors.js.map +1 -0
- package/dist/esm/index.d.ts +8 -0
- package/dist/esm/index.js +6 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/package.json +1 -0
- package/dist/esm/session/manager.d.ts +45 -0
- package/dist/esm/session/manager.js +223 -0
- package/dist/esm/session/manager.js.map +1 -0
- package/dist/esm/session/types.d.ts +16 -0
- package/dist/esm/session/types.js +2 -0
- package/dist/esm/session/types.js.map +1 -0
- package/dist/esm/signer.d.ts +262 -0
- package/dist/esm/signer.js +30 -0
- package/dist/esm/signer.js.map +1 -0
- package/dist/esm/types.d.ts +14 -0
- package/dist/esm/types.js +9 -0
- package/dist/esm/types.js.map +1 -0
- package/dist/esm/utils/base64UrlEncode.d.ts +1 -0
- package/dist/esm/utils/base64UrlEncode.js +8 -0
- package/dist/esm/utils/base64UrlEncode.js.map +1 -0
- package/dist/esm/utils/generateRandomBuffer.d.ts +1 -0
- package/dist/esm/utils/generateRandomBuffer.js +6 -0
- package/dist/esm/utils/generateRandomBuffer.js.map +1 -0
- package/dist/esm/version.d.ts +1 -0
- package/dist/esm/version.js +2 -0
- package/dist/esm/version.js.map +1 -0
- package/dist/types/base.d.ts +89 -0
- package/dist/types/base.d.ts.map +1 -0
- package/dist/types/client/base.d.ts +246 -0
- package/dist/types/client/base.d.ts.map +1 -0
- package/dist/types/client/index.d.ts +151 -0
- package/dist/types/client/index.d.ts.map +1 -0
- package/dist/types/client/types.d.ts +107 -0
- package/dist/types/client/types.d.ts.map +1 -0
- package/dist/types/errors.d.ts +5 -0
- package/dist/types/errors.d.ts.map +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/session/manager.d.ts +46 -0
- package/dist/types/session/manager.d.ts.map +1 -0
- package/dist/types/session/types.d.ts +17 -0
- package/dist/types/session/types.d.ts.map +1 -0
- package/dist/types/signer.d.ts +269 -0
- package/dist/types/signer.d.ts.map +1 -0
- package/dist/types/types.d.ts +15 -0
- package/dist/types/types.d.ts.map +1 -0
- package/dist/types/utils/base64UrlEncode.d.ts +2 -0
- package/dist/types/utils/base64UrlEncode.d.ts.map +1 -0
- package/dist/types/utils/generateRandomBuffer.d.ts +2 -0
- package/dist/types/utils/generateRandomBuffer.d.ts.map +1 -0
- package/dist/types/version.d.ts +2 -0
- package/dist/types/version.d.ts.map +1 -0
- package/package.json +79 -0
- package/src/base.ts +386 -0
- package/src/client/base.ts +399 -0
- package/src/client/index.ts +267 -0
- package/src/client/types.ts +121 -0
- package/src/errors.ts +15 -0
- package/src/index.ts +10 -0
- package/src/session/manager.ts +249 -0
- package/src/session/types.ts +16 -0
- package/src/signer.ts +55 -0
- package/src/types.ts +17 -0
- package/src/utils/base64UrlEncode.ts +7 -0
- package/src/utils/generateRandomBuffer.ts +5 -0
- package/src/version.ts +3 -0
package/src/base.ts
ADDED
|
@@ -0,0 +1,386 @@
|
|
|
1
|
+
import { takeBytes, type SmartAccountAuthenticator } from "@aa-sdk/core";
|
|
2
|
+
import {
|
|
3
|
+
hashMessage,
|
|
4
|
+
hashTypedData,
|
|
5
|
+
keccak256,
|
|
6
|
+
serializeTransaction,
|
|
7
|
+
type CustomSource,
|
|
8
|
+
type Hex,
|
|
9
|
+
type LocalAccount,
|
|
10
|
+
type SignableMessage,
|
|
11
|
+
type TypedData,
|
|
12
|
+
type TypedDataDefinition,
|
|
13
|
+
} from "viem";
|
|
14
|
+
import { toAccount } from "viem/accounts";
|
|
15
|
+
import type { Mutate, StoreApi } from "zustand";
|
|
16
|
+
import { subscribeWithSelector } from "zustand/middleware";
|
|
17
|
+
import { createStore } from "zustand/vanilla";
|
|
18
|
+
import type { BaseSignerClient } from "./client/base";
|
|
19
|
+
import type { User } from "./client/types";
|
|
20
|
+
import { NotAuthenticatedError } from "./errors.js";
|
|
21
|
+
import {
|
|
22
|
+
SessionManager,
|
|
23
|
+
type SessionManagerParams,
|
|
24
|
+
} from "./session/manager.js";
|
|
25
|
+
import type { AuthParams } from "./signer";
|
|
26
|
+
import {
|
|
27
|
+
AlchemySignerStatus,
|
|
28
|
+
type AlchemySignerEvent,
|
|
29
|
+
type AlchemySignerEvents,
|
|
30
|
+
} from "./types.js";
|
|
31
|
+
|
|
32
|
+
export interface BaseAlchemySignerParams<TClient extends BaseSignerClient> {
|
|
33
|
+
client: TClient;
|
|
34
|
+
sessionConfig?: Omit<SessionManagerParams, "client">;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
type AlchemySignerStore = {
|
|
38
|
+
user: User | null;
|
|
39
|
+
status: AlchemySignerStatus;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
type InternalStore = Mutate<
|
|
43
|
+
StoreApi<AlchemySignerStore>,
|
|
44
|
+
[["zustand/subscribeWithSelector", never]]
|
|
45
|
+
>;
|
|
46
|
+
|
|
47
|
+
export abstract class BaseAlchemySigner<TClient extends BaseSignerClient>
|
|
48
|
+
implements SmartAccountAuthenticator<AuthParams, User, TClient>
|
|
49
|
+
{
|
|
50
|
+
signerType: string = "alchemy-signer";
|
|
51
|
+
inner: TClient;
|
|
52
|
+
private sessionManager: SessionManager;
|
|
53
|
+
private store: InternalStore;
|
|
54
|
+
|
|
55
|
+
constructor({ client, sessionConfig }: BaseAlchemySignerParams<TClient>) {
|
|
56
|
+
this.inner = client;
|
|
57
|
+
this.store = createStore(
|
|
58
|
+
subscribeWithSelector(
|
|
59
|
+
() =>
|
|
60
|
+
({
|
|
61
|
+
user: null,
|
|
62
|
+
status: AlchemySignerStatus.INITIALIZING,
|
|
63
|
+
} satisfies AlchemySignerStore)
|
|
64
|
+
)
|
|
65
|
+
);
|
|
66
|
+
// NOTE: it's important that the session manager share a client
|
|
67
|
+
// with the signer. The SessionManager leverages the Signer's client
|
|
68
|
+
// to manage session state.
|
|
69
|
+
this.sessionManager = new SessionManager({
|
|
70
|
+
...sessionConfig,
|
|
71
|
+
client: this.inner,
|
|
72
|
+
});
|
|
73
|
+
this.store = createStore(
|
|
74
|
+
subscribeWithSelector(
|
|
75
|
+
() =>
|
|
76
|
+
({
|
|
77
|
+
user: null,
|
|
78
|
+
status: AlchemySignerStatus.INITIALIZING,
|
|
79
|
+
} satisfies AlchemySignerStore)
|
|
80
|
+
)
|
|
81
|
+
);
|
|
82
|
+
// register listeners first
|
|
83
|
+
this.registerListeners();
|
|
84
|
+
// then initialize so that we can catch those events
|
|
85
|
+
this.sessionManager.initialize();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* Allows you to subscribe to events emitted by the signer
|
|
90
|
+
*
|
|
91
|
+
* @param event the event to subscribe to
|
|
92
|
+
* @param listener the function to run when the event is emitted
|
|
93
|
+
* @returns a function to remove the listener
|
|
94
|
+
*/
|
|
95
|
+
on = <E extends AlchemySignerEvent>(
|
|
96
|
+
event: E,
|
|
97
|
+
listener: AlchemySignerEvents[E]
|
|
98
|
+
) => {
|
|
99
|
+
// NOTE: we're using zustand here to handle this because we are able to use the fireImmediately
|
|
100
|
+
// option which deals with a possible race condition where the listener is added after the event
|
|
101
|
+
// is fired. In the Client and SessionManager we use EventEmitter because it's easier to handle internally
|
|
102
|
+
switch (event) {
|
|
103
|
+
case "connected":
|
|
104
|
+
return this.store.subscribe(
|
|
105
|
+
({ status }) => status,
|
|
106
|
+
(status) =>
|
|
107
|
+
status === AlchemySignerStatus.CONNECTED &&
|
|
108
|
+
(listener as AlchemySignerEvents["connected"])(
|
|
109
|
+
this.store.getState().user!
|
|
110
|
+
),
|
|
111
|
+
{ fireImmediately: true }
|
|
112
|
+
);
|
|
113
|
+
case "disconnected":
|
|
114
|
+
return this.store.subscribe(
|
|
115
|
+
({ status }) => status,
|
|
116
|
+
(status) =>
|
|
117
|
+
status === AlchemySignerStatus.DISCONNECTED &&
|
|
118
|
+
(listener as AlchemySignerEvents["disconnected"])(),
|
|
119
|
+
{ fireImmediately: true }
|
|
120
|
+
);
|
|
121
|
+
case "statusChanged":
|
|
122
|
+
return this.store.subscribe(
|
|
123
|
+
({ status }) => status,
|
|
124
|
+
listener as AlchemySignerEvents["statusChanged"],
|
|
125
|
+
{ fireImmediately: true }
|
|
126
|
+
);
|
|
127
|
+
default:
|
|
128
|
+
throw new Error(`Uknown event type ${event}`);
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Authenticate a user with either an email or a passkey and create a session for that user
|
|
134
|
+
*
|
|
135
|
+
* @param params - undefined if passkey login, otherwise an object with email and bundle to resolve
|
|
136
|
+
* @returns the user that was authenticated
|
|
137
|
+
*/
|
|
138
|
+
authenticate: (params: AuthParams) => Promise<User> = async (params) => {
|
|
139
|
+
if (params.type === "email") {
|
|
140
|
+
return this.authenticateWithEmail(params);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return this.authenticateWithPasskey(params);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* NOTE: right now this only clears the session locally.
|
|
148
|
+
*/
|
|
149
|
+
disconnect: () => Promise<void> = async () => {
|
|
150
|
+
await this.inner.disconnect();
|
|
151
|
+
};
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Gets the current logged in user
|
|
155
|
+
* If a user has an ongoing session, it will use that session and
|
|
156
|
+
* try to authenticate
|
|
157
|
+
*
|
|
158
|
+
* @throws if there is no user logged in
|
|
159
|
+
* @returns the current user
|
|
160
|
+
*/
|
|
161
|
+
getAuthDetails: () => Promise<User> = async () => {
|
|
162
|
+
const sessionUser = await this.sessionManager.getSessionUser();
|
|
163
|
+
if (sessionUser != null) {
|
|
164
|
+
return sessionUser;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return this.inner.whoami();
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
getAddress: () => Promise<`0x${string}`> = async () => {
|
|
171
|
+
const { address } = await this.inner.whoami();
|
|
172
|
+
|
|
173
|
+
return address;
|
|
174
|
+
};
|
|
175
|
+
|
|
176
|
+
signMessage: (msg: SignableMessage) => Promise<`0x${string}`> = async (
|
|
177
|
+
msg
|
|
178
|
+
) => {
|
|
179
|
+
const messageHash = hashMessage(msg);
|
|
180
|
+
|
|
181
|
+
return this.inner.signRawMessage(messageHash);
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
signTypedData: <
|
|
185
|
+
const TTypedData extends TypedData | { [key: string]: unknown },
|
|
186
|
+
TPrimaryType extends keyof TTypedData | "EIP712Domain" = keyof TTypedData
|
|
187
|
+
>(
|
|
188
|
+
params: TypedDataDefinition<TTypedData, TPrimaryType>
|
|
189
|
+
) => Promise<Hex> = async (params) => {
|
|
190
|
+
const messageHash = hashTypedData(params);
|
|
191
|
+
|
|
192
|
+
return this.inner.signRawMessage(messageHash);
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
signTransaction: CustomSource["signTransaction"] = async (tx, args) => {
|
|
196
|
+
const serializeFn = args?.serializer ?? serializeTransaction;
|
|
197
|
+
const serializedTx = serializeFn(tx);
|
|
198
|
+
const signatureHex = await this.inner.signRawMessage(
|
|
199
|
+
keccak256(serializedTx)
|
|
200
|
+
);
|
|
201
|
+
|
|
202
|
+
const signature = {
|
|
203
|
+
r: takeBytes(signatureHex, { count: 32 }),
|
|
204
|
+
s: takeBytes(signatureHex, { count: 32, offset: 32 }),
|
|
205
|
+
v: BigInt(takeBytes(signatureHex, { count: 1, offset: 64 })),
|
|
206
|
+
};
|
|
207
|
+
|
|
208
|
+
return serializeFn(tx, signature);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Unauthenticated call to look up a user's organizationId by email
|
|
213
|
+
*
|
|
214
|
+
* @param email the email to lookup
|
|
215
|
+
* @returns the organization id for the user if they exist
|
|
216
|
+
*/
|
|
217
|
+
getUser: (email: string) => Promise<{ orgId: string } | null> = async (
|
|
218
|
+
email
|
|
219
|
+
) => {
|
|
220
|
+
const result = await this.inner.lookupUserByEmail(email);
|
|
221
|
+
|
|
222
|
+
if (result.orgId == null) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
return {
|
|
227
|
+
orgId: result.orgId,
|
|
228
|
+
};
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Adds a passkey to the user's account
|
|
233
|
+
*
|
|
234
|
+
* @param params optional parameters for the passkey creation
|
|
235
|
+
* @returns an array of the authenticator ids added to the user
|
|
236
|
+
*/
|
|
237
|
+
addPasskey: (params?: CredentialCreationOptions) => Promise<string[]> =
|
|
238
|
+
async (params) => {
|
|
239
|
+
return this.inner.addPasskey(params ?? {});
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Used to export the wallet for a given user
|
|
244
|
+
* If the user is authenticated with an Email, this will return a seed phrase
|
|
245
|
+
* If the user is authenticated with a Passkey, this will return a private key
|
|
246
|
+
*
|
|
247
|
+
* @param params export wallet parameters
|
|
248
|
+
* @returns true if the wallet was exported successfully
|
|
249
|
+
*/
|
|
250
|
+
exportWallet: (
|
|
251
|
+
params: Parameters<(typeof this.inner)["exportWallet"]>[0]
|
|
252
|
+
) => Promise<boolean> = async (params) => {
|
|
253
|
+
return this.inner.exportWallet(params);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* This method lets you adapt your AlchemySigner to a viem LocalAccount, which
|
|
258
|
+
* will let you use the signer as an EOA directly.
|
|
259
|
+
*
|
|
260
|
+
* @throws if your signer is not authenticated
|
|
261
|
+
* @returns a LocalAccount object that can be used with viem's wallet client
|
|
262
|
+
*/
|
|
263
|
+
toViemAccount: () => LocalAccount = () => {
|
|
264
|
+
// if we want this method to be synchronous, then we need to do this check here
|
|
265
|
+
// otherwise we can use the sessionManager to get the user
|
|
266
|
+
if (!this.inner.getUser()) {
|
|
267
|
+
throw new NotAuthenticatedError();
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return toAccount({
|
|
271
|
+
address: this.inner.getUser()!.address,
|
|
272
|
+
signMessage: (msg) => this.signMessage(msg.message),
|
|
273
|
+
signTypedData: <
|
|
274
|
+
const typedData extends TypedData | Record<string, unknown>,
|
|
275
|
+
primaryType extends keyof typedData | "EIP712Domain" = keyof typedData
|
|
276
|
+
>(
|
|
277
|
+
typedDataDefinition: TypedDataDefinition<typedData, primaryType>
|
|
278
|
+
) => this.signTypedData<typedData, primaryType>(typedDataDefinition),
|
|
279
|
+
signTransaction: this.signTransaction,
|
|
280
|
+
});
|
|
281
|
+
};
|
|
282
|
+
|
|
283
|
+
private authenticateWithEmail = async (
|
|
284
|
+
params: Extract<AuthParams, { type: "email" }>
|
|
285
|
+
): Promise<User> => {
|
|
286
|
+
if ("email" in params) {
|
|
287
|
+
const existingUser = await this.getUser(params.email);
|
|
288
|
+
|
|
289
|
+
const { orgId } = existingUser
|
|
290
|
+
? await this.inner.initEmailAuth({
|
|
291
|
+
email: params.email,
|
|
292
|
+
expirationSeconds: this.sessionManager.expirationTimeMs,
|
|
293
|
+
redirectParams: params.redirectParams,
|
|
294
|
+
})
|
|
295
|
+
: await this.inner.createAccount({
|
|
296
|
+
type: "email",
|
|
297
|
+
email: params.email,
|
|
298
|
+
expirationSeconds: this.sessionManager.expirationTimeMs,
|
|
299
|
+
redirectParams: params.redirectParams,
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
this.sessionManager.setTemporarySession({ orgId });
|
|
303
|
+
this.store.setState({ status: AlchemySignerStatus.AWAITING_EMAIL_AUTH });
|
|
304
|
+
|
|
305
|
+
// We wait for the session manager to emit a connected event if
|
|
306
|
+
// cross tab sessions are permitted
|
|
307
|
+
return new Promise<User>((resolve) => {
|
|
308
|
+
const removeListener = this.sessionManager.on(
|
|
309
|
+
"connected",
|
|
310
|
+
(session) => {
|
|
311
|
+
resolve(session.user);
|
|
312
|
+
removeListener();
|
|
313
|
+
}
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
} else {
|
|
317
|
+
const temporarySession = params.orgId
|
|
318
|
+
? { orgId: params.orgId }
|
|
319
|
+
: this.sessionManager.getTemporarySession();
|
|
320
|
+
|
|
321
|
+
if (!temporarySession) {
|
|
322
|
+
this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });
|
|
323
|
+
throw new Error("Could not find email auth init session!");
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
const user = await this.inner.completeEmailAuth({
|
|
327
|
+
bundle: params.bundle,
|
|
328
|
+
orgId: temporarySession.orgId,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
return user;
|
|
332
|
+
}
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
private authenticateWithPasskey = async (
|
|
336
|
+
args: Extract<AuthParams, { type: "passkey" }>
|
|
337
|
+
) => {
|
|
338
|
+
let user: User;
|
|
339
|
+
if (args.createNew) {
|
|
340
|
+
const result = await this.inner.createAccount(args);
|
|
341
|
+
// account creation for passkeys returns the whoami response so we don't have to
|
|
342
|
+
// call it again after signup
|
|
343
|
+
user = {
|
|
344
|
+
address: result.address!,
|
|
345
|
+
userId: result.userId!,
|
|
346
|
+
orgId: result.orgId,
|
|
347
|
+
};
|
|
348
|
+
} else {
|
|
349
|
+
user = await this.inner.lookupUserWithPasskey();
|
|
350
|
+
if (!user) {
|
|
351
|
+
this.store.setState({ status: AlchemySignerStatus.DISCONNECTED });
|
|
352
|
+
throw new Error("No user found");
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return user;
|
|
357
|
+
};
|
|
358
|
+
|
|
359
|
+
private registerListeners = () => {
|
|
360
|
+
this.sessionManager.on("connected", (session) => {
|
|
361
|
+
this.store.setState({
|
|
362
|
+
user: session.user,
|
|
363
|
+
status: AlchemySignerStatus.CONNECTED,
|
|
364
|
+
});
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
this.sessionManager.on("disconnected", () => {
|
|
368
|
+
this.store.setState({
|
|
369
|
+
user: null,
|
|
370
|
+
status: AlchemySignerStatus.DISCONNECTED,
|
|
371
|
+
});
|
|
372
|
+
});
|
|
373
|
+
|
|
374
|
+
this.sessionManager.on("initialized", () => {
|
|
375
|
+
this.store.setState((state) => ({
|
|
376
|
+
status: state.user
|
|
377
|
+
? AlchemySignerStatus.CONNECTED
|
|
378
|
+
: AlchemySignerStatus.DISCONNECTED,
|
|
379
|
+
}));
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
this.inner.on("authenticating", () => {
|
|
383
|
+
this.store.setState({ status: AlchemySignerStatus.AUTHENTICATING });
|
|
384
|
+
});
|
|
385
|
+
};
|
|
386
|
+
}
|