@0xkey-io/react-native-wallet-kit 0.1.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.
Files changed (61) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +93 -0
  3. package/dist/hooks/use-0xkey.d.ts +3 -0
  4. package/dist/hooks/use-0xkey.d.ts.map +1 -0
  5. package/dist/hooks/use-0xkey.js +15 -0
  6. package/dist/hooks/use-0xkey.js.map +1 -0
  7. package/dist/hooks/use-0xkey.mjs +13 -0
  8. package/dist/hooks/use-0xkey.mjs.map +1 -0
  9. package/dist/index.d.ts +21 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +55 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/index.mjs +6 -0
  14. package/dist/index.mjs.map +1 -0
  15. package/dist/providers/Types.d.ts +275 -0
  16. package/dist/providers/Types.d.ts.map +1 -0
  17. package/dist/providers/Types.js +9 -0
  18. package/dist/providers/Types.js.map +1 -0
  19. package/dist/providers/Types.mjs +7 -0
  20. package/dist/providers/Types.mjs.map +1 -0
  21. package/dist/providers/ZeroXKeyProvider.d.ts +39 -0
  22. package/dist/providers/ZeroXKeyProvider.d.ts.map +1 -0
  23. package/dist/providers/ZeroXKeyProvider.js +1846 -0
  24. package/dist/providers/ZeroXKeyProvider.js.map +1 -0
  25. package/dist/providers/ZeroXKeyProvider.mjs +1844 -0
  26. package/dist/providers/ZeroXKeyProvider.mjs.map +1 -0
  27. package/dist/providers/index.d.ts +4 -0
  28. package/dist/providers/index.d.ts.map +1 -0
  29. package/dist/tests/oauth-test.d.ts +2 -0
  30. package/dist/tests/oauth-test.d.ts.map +1 -0
  31. package/dist/typedoc-entry/index.d.ts +5 -0
  32. package/dist/typedoc-entry/index.d.ts.map +1 -0
  33. package/dist/types/base.d.ts +137 -0
  34. package/dist/types/base.d.ts.map +1 -0
  35. package/dist/types/base.js +48 -0
  36. package/dist/types/base.js.map +1 -0
  37. package/dist/types/base.mjs +48 -0
  38. package/dist/types/base.mjs.map +1 -0
  39. package/dist/types/method-types.d.ts +102 -0
  40. package/dist/types/method-types.d.ts.map +1 -0
  41. package/dist/utils/index.d.ts +4 -0
  42. package/dist/utils/index.d.ts.map +1 -0
  43. package/dist/utils/oauth.d.ts +240 -0
  44. package/dist/utils/oauth.d.ts.map +1 -0
  45. package/dist/utils/oauth.js +340 -0
  46. package/dist/utils/oauth.js.map +1 -0
  47. package/dist/utils/oauth.mjs +319 -0
  48. package/dist/utils/oauth.mjs.map +1 -0
  49. package/dist/utils/timers.d.ts +73 -0
  50. package/dist/utils/timers.d.ts.map +1 -0
  51. package/dist/utils/timers.js +132 -0
  52. package/dist/utils/timers.js.map +1 -0
  53. package/dist/utils/timers.mjs +122 -0
  54. package/dist/utils/timers.mjs.map +1 -0
  55. package/dist/utils/utils.d.ts +27 -0
  56. package/dist/utils/utils.d.ts.map +1 -0
  57. package/dist/utils/utils.js +37 -0
  58. package/dist/utils/utils.js.map +1 -0
  59. package/dist/utils/utils.mjs +33 -0
  60. package/dist/utils/utils.mjs.map +1 -0
  61. package/package.json +80 -0
@@ -0,0 +1,1844 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { withZeroXKeyErrorHandling, isValidSession, SESSION_WARNING_THRESHOLD_MS } from '../utils/utils.mjs';
3
+ import { clearKey, setTimeoutInMap, setCappedTimeoutInMap, clearKeys, clearAll } from '../utils/timers.mjs';
4
+ import { generateChallengePair, storePKCEVerifier, buildOAuthUrl, parseInAppBrowserResult, handlePKCEFlow, completeOAuthFlow, exchangeCodeForToken, ZEROXKEY_OAUTH_REDIRECT_URL } from '../utils/oauth.mjs';
5
+ import { DEFAULT_SESSION_EXPIRATION_IN_SECONDS, OtpType, getAuthProxyConfig, ZeroXKeyClient } from '@0xkey-io/core';
6
+ import { useState, useRef, useCallback, useEffect } from 'react';
7
+ import { Platform } from 'react-native';
8
+ import DeviceInfo from 'react-native-device-info';
9
+ import { InAppBrowser } from 'react-native-inappbrowser-reborn';
10
+ import { sha256 } from '@noble/hashes/sha2';
11
+ import { bytesToHex } from '@noble/hashes/utils';
12
+ import { ZeroXKeyError, ZeroXKeyErrorCodes, AuthAction, OAuthProviders, ZeroXKeyNetworkError } from '@0xkey-io/sdk-types';
13
+ import { AuthState, AuthMethod, ClientState } from '../types/base.mjs';
14
+ import { ClientContext } from './Types.mjs';
15
+ import { generateP256KeyPair, decryptExportBundle, encryptWalletToBundle, encryptPrivateKeyToBundle } from '@0xkey-io/crypto';
16
+
17
+ /**
18
+ * Provides ZeroXKey client authentication, session management, wallet operations, and user profile management
19
+ * for the React Native Wallet Kit SDK. This context provider encapsulates all core authentication flows (Passkey, OTP, OAuth),
20
+ * session lifecycle (creation, expiration, refresh), wallet import/export, and user profile updates (email, phone, name).
21
+ *
22
+ * The provider automatically initializes the ZeroXKey client, fetches configuration (including proxy auth config if needed),
23
+ * and synchronizes session and authentication state. It exposes a comprehensive set of methods for authentication flows,
24
+ * wallet management, and user profile operations, as well as UI handlers for modal-driven flows.
25
+ *
26
+ * Features:
27
+ * - Passkey, OTP (Email/SMS), and OAuth (Google, Apple, Facebook, Discord, X) authentication and sign-up flows.
28
+ * - React Native-specific OAuth: opens an in-app browser (Custom Tabs/Safari View Controller) and deep-links back via the configured app scheme.
29
+ * - Session management: creation, expiration scheduling, refresh, and clearing.
30
+ * - Wallet management: fetch, import, export, account management.
31
+ * - User profile management: email, phone, name, OAuth provider, and passkey linking/removal.
32
+ * - Error handling and callback integration for custom error and event responses.
33
+ *
34
+ * Usage:
35
+ * Wrap your application with `ZeroXKeyProvider` to enable authentication and wallet features via context.
36
+ *
37
+ * @param config - The ZeroXKey provider configuration object.
38
+ * @param children - React children to be rendered within the provider.
39
+ * @param callbacks - Optional callbacks for error handling and session events.
40
+ *
41
+ * @returns A React context provider exposing authentication, wallet, and user management methods and state.
42
+ */
43
+ const ZeroXKeyProvider = ({ config, children, callbacks, }) => {
44
+ const [client, setClient] = useState(undefined);
45
+ const [session, setSession] = useState(undefined);
46
+ const [masterConfig, setMasterConfig] = useState(undefined);
47
+ const [wallets, setWallets] = useState([]);
48
+ const [user, setUser] = useState(undefined);
49
+ const [clientState, setClientState] = useState();
50
+ const [authState, setAuthState] = useState(AuthState.Unauthenticated);
51
+ const expiryTimeoutsRef = useRef({});
52
+ const proxyAuthConfigRef = useRef(null);
53
+ const [allSessions, setAllSessions] = useState(undefined);
54
+ // if there is no authProxyConfigId or if autoFetchWalletKitConfig is specifically
55
+ // set to false, we don't need to fetch the config
56
+ const shouldFetchWalletKitConfig = config.authProxyConfigId != null &&
57
+ config.authProxyConfigId !== "" &&
58
+ config.autoFetchWalletKitConfig !== false;
59
+ const buildConfig = (proxyAuthConfig) => {
60
+ // Juggle the local overrides with the values set in the dashboard (proxyAuthConfig).
61
+ // Normalize potentially empty string values coming from the app-level config
62
+ const sanitizedAuthProxyUrl = config.authProxyUrl && config.authProxyUrl.trim()
63
+ ? config.authProxyUrl
64
+ : undefined;
65
+ // Resolve OTP enablement
66
+ const emailOtpEnabled = config.auth?.otp?.email ??
67
+ proxyAuthConfig?.enabledProviders.includes("email") ??
68
+ false;
69
+ const smsOtpEnabled = config.auth?.otp?.sms ??
70
+ proxyAuthConfig?.enabledProviders.includes("sms") ??
71
+ false;
72
+ // Resolve shared redirect; do NOT attach scheme here. We'll attach in handler on demand.
73
+ const appScheme = config.auth?.oauth?.appScheme ?? undefined;
74
+ const redirectUrl = config.auth?.oauth?.redirectUri ??
75
+ proxyAuthConfig?.oauthRedirectUrl ??
76
+ ZEROXKEY_OAUTH_REDIRECT_URL;
77
+ // Warn if they are trying to set auth proxy only settings directly
78
+ if (proxyAuthConfig) {
79
+ if (config.auth?.sessionExpirationSeconds) {
80
+ console.warn("ZeroXKey SDK warning. You have set sessionExpirationSeconds directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure session expiration in the ZeroXKey dashboard.");
81
+ }
82
+ if (config.auth?.otp?.alphanumeric !== undefined &&
83
+ shouldFetchWalletKitConfig) {
84
+ console.warn("ZeroXKey SDK warning. You have set otpAlphanumeric directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the ZeroXKey dashboard.");
85
+ }
86
+ if (config.auth?.otp?.length && shouldFetchWalletKitConfig) {
87
+ console.warn("ZeroXKey SDK warning. You have set otpLength directly in the ZeroXKeyProvider. This setting will be ignored because you are using an auth proxy. Please configure OTP settings in the ZeroXKey dashboard.");
88
+ }
89
+ }
90
+ // These are settings that can only be set via the auth proxy config
91
+ const authProxyPrioSettings = {
92
+ sessionExpirationSeconds: proxyAuthConfig?.sessionExpirationSeconds ??
93
+ config.auth?.sessionExpirationSeconds,
94
+ otp: {
95
+ alphanumeric: proxyAuthConfig?.otpAlphanumeric ??
96
+ config.auth?.otp?.alphanumeric ??
97
+ true,
98
+ length: proxyAuthConfig?.otpLength ?? config.auth?.otp?.length ?? "6",
99
+ },
100
+ };
101
+ return {
102
+ ...config,
103
+ // Ensure empty strings are not forwarded as URLs
104
+ authProxyUrl: sanitizedAuthProxyUrl,
105
+ // Overrides:
106
+ auth: {
107
+ ...config.auth,
108
+ // Proxy-controlled settings
109
+ sessionExpirationSeconds: authProxyPrioSettings.sessionExpirationSeconds,
110
+ otp: {
111
+ ...config.auth?.otp,
112
+ // Enablement flags
113
+ email: emailOtpEnabled,
114
+ sms: smsOtpEnabled,
115
+ // Proxy-only settings
116
+ alphanumeric: authProxyPrioSettings.otp.alphanumeric,
117
+ length: authProxyPrioSettings.otp.length,
118
+ },
119
+ // OAuth shared settings
120
+ oauth: {
121
+ ...config.auth?.oauth,
122
+ ...(appScheme && { appScheme }),
123
+ redirectUri: redirectUrl,
124
+ },
125
+ autoRefreshSession: config.auth?.autoRefreshSession ?? true,
126
+ },
127
+ autoRefreshManagedState: config.autoRefreshManagedState ?? true,
128
+ };
129
+ };
130
+ const getOauthProviderSettings = (provider) => {
131
+ const oauth = masterConfig?.auth?.oauth;
132
+ const providerConfig = oauth ? oauth[provider] : undefined;
133
+ const providerObjectConfig = providerConfig && typeof providerConfig === "object"
134
+ ? providerConfig
135
+ : undefined;
136
+ const proxyClientIds = proxyAuthConfigRef.current?.oauthClientIds;
137
+ const clientId = providerObjectConfig?.clientId ??
138
+ (proxyClientIds ? proxyClientIds[provider] : undefined);
139
+ const appScheme = oauth?.appScheme;
140
+ // For Discord and X, default to scheme-based deep link if not explicitly provided.
141
+ const redirectUri = providerObjectConfig?.redirectUri ??
142
+ ((provider === "discord" || provider === "x") && appScheme
143
+ ? `${appScheme}://`
144
+ : (oauth?.redirectUri ??
145
+ proxyAuthConfigRef.current?.oauthRedirectUrl ??
146
+ ZEROXKEY_OAUTH_REDIRECT_URL));
147
+ return { clientId, redirectUri, appScheme };
148
+ };
149
+ /**
150
+ * Initializes the ZeroXKey client with the provided configuration.
151
+ * This function sets up the client, fetches the proxy auth config if needed,
152
+ * and prepares the client for use in authentication and wallet operations.
153
+ *
154
+ * @internal
155
+ */
156
+ const initializeClient = async () => {
157
+ if (!masterConfig || client || clientState == ClientState.Loading)
158
+ return;
159
+ try {
160
+ setClientState(ClientState.Loading);
161
+ const zeroXKeyClient = new ZeroXKeyClient({
162
+ apiBaseUrl: masterConfig.apiBaseUrl,
163
+ authProxyUrl: masterConfig.authProxyUrl,
164
+ authProxyConfigId: masterConfig.authProxyConfigId,
165
+ organizationId: masterConfig.organizationId,
166
+ defaultStamperType: masterConfig.defaultStamperType,
167
+ // Define passkey and wallet config here. If we don't pass it into the client, Mr. Client will assume that we don't want to use passkeys/wallets and not create the stamper!
168
+ passkeyConfig: {
169
+ rpId: masterConfig.passkeyConfig?.rpId,
170
+ timeout: masterConfig.passkeyConfig?.timeout || 60000, // 60 seconds
171
+ userVerification: masterConfig.passkeyConfig?.userVerification || "preferred",
172
+ allowCredentials: masterConfig.passkeyConfig?.allowCredentials || [],
173
+ },
174
+ });
175
+ await zeroXKeyClient.init();
176
+ setClient(zeroXKeyClient);
177
+ // Don't set clientState to ready until we fetch the proxy auth config (See other fetchProxyAuthConfig useEffect)
178
+ }
179
+ catch (error) {
180
+ setClientState(ClientState.Error);
181
+ if (error instanceof ZeroXKeyError ||
182
+ error instanceof ZeroXKeyNetworkError) {
183
+ callbacks?.onError?.(error);
184
+ }
185
+ else {
186
+ callbacks?.onError?.(new ZeroXKeyError(`Failed to initialize ZeroXKey client`, ZeroXKeyErrorCodes.INITIALIZE_CLIENT_ERROR, error));
187
+ }
188
+ }
189
+ };
190
+ /**
191
+ * @internal
192
+ * Schedules a session expiration and warning timer for the given session key.
193
+ *
194
+ * - Sets up two timers: one for warning before expiry and one for actual expiry.
195
+ * - Uses capped timeouts under the hood so delays > 24.8 days are safe (see utils/timers.ts).
196
+ *
197
+ * @param params.sessionKey - The key of the session to schedule expiration for.
198
+ * @param params.expiry - The expiration time in seconds since epoch.
199
+ * @throws {ZeroXKeyError} If an error occurs while scheduling the session expiration.
200
+ */
201
+ async function scheduleSessionExpiration(params) {
202
+ const { sessionKey, expiry } = params;
203
+ try {
204
+ const warnKey = `${sessionKey}-warning`;
205
+ // Replace any prior timers for this session
206
+ clearKey(expiryTimeoutsRef.current, sessionKey);
207
+ clearKey(expiryTimeoutsRef.current, warnKey);
208
+ const now = Date.now();
209
+ const expiryMs = expiry * 1000;
210
+ const timeUntilExpiry = expiryMs - now;
211
+ const beforeExpiry = async () => {
212
+ const activeSession = await getSession();
213
+ if (!activeSession && expiryTimeoutsRef.current[warnKey]) {
214
+ // Keep nudging until session materializes (short 10s timer is fine)
215
+ setTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, 10_000);
216
+ return;
217
+ }
218
+ const session = await getSession({ sessionKey });
219
+ if (!session)
220
+ return;
221
+ callbacks?.beforeSessionExpiry?.({ sessionKey });
222
+ if (masterConfig?.auth?.autoRefreshSession) {
223
+ await refreshSession({
224
+ expirationSeconds: session.expirationSeconds,
225
+ sessionKey,
226
+ });
227
+ }
228
+ };
229
+ const expireSession = async () => {
230
+ const expiredSession = await getSession({ sessionKey });
231
+ if (!expiredSession)
232
+ return;
233
+ callbacks?.onSessionExpired?.({ sessionKey });
234
+ if ((await getActiveSessionKey()) === sessionKey) {
235
+ setSession(undefined);
236
+ }
237
+ setAllSessions((prev) => {
238
+ if (!prev)
239
+ return prev;
240
+ const next = { ...prev };
241
+ delete next[sessionKey];
242
+ return next;
243
+ });
244
+ await clearSession({ sessionKey });
245
+ // Remove timers for this session
246
+ clearKey(expiryTimeoutsRef.current, sessionKey);
247
+ clearKey(expiryTimeoutsRef.current, warnKey);
248
+ await logout();
249
+ };
250
+ // Already expired → expire immediately
251
+ if (timeUntilExpiry <= 0) {
252
+ await expireSession();
253
+ return;
254
+ }
255
+ // Warning timer (if threshold is in the future)
256
+ const warnAt = expiryMs - SESSION_WARNING_THRESHOLD_MS;
257
+ if (warnAt <= now) {
258
+ void beforeExpiry(); // fire-and-forget is fine
259
+ }
260
+ else {
261
+ setCappedTimeoutInMap(expiryTimeoutsRef.current, warnKey, beforeExpiry, warnAt - now);
262
+ }
263
+ // Actual expiry timer (safe for long delays)
264
+ setCappedTimeoutInMap(expiryTimeoutsRef.current, sessionKey, expireSession, timeUntilExpiry);
265
+ }
266
+ catch (error) {
267
+ if (error instanceof ZeroXKeyError ||
268
+ error instanceof ZeroXKeyNetworkError) {
269
+ callbacks?.onError?.(error);
270
+ }
271
+ else {
272
+ callbacks?.onError?.(new ZeroXKeyError(`Failed to schedule session expiration for ${sessionKey}`, ZeroXKeyErrorCodes.SCHEDULE_SESSION_EXPIRY_ERROR, error));
273
+ }
274
+ }
275
+ }
276
+ /**
277
+ * Clears all scheduled session timers (warning + expiry).
278
+ *
279
+ * - Removes all active timers managed by this client.
280
+ * - Useful on re-init or logout to avoid stale timers.
281
+ *
282
+ * @throws {ZeroXKeyError} If an error occurs while clearing the timers.
283
+ */
284
+ function clearSessionTimeouts(sessionKeys) {
285
+ try {
286
+ if (sessionKeys) {
287
+ clearKeys(expiryTimeoutsRef.current, sessionKeys);
288
+ }
289
+ else {
290
+ clearAll(expiryTimeoutsRef.current); // clears & deletes everything
291
+ }
292
+ }
293
+ catch (error) {
294
+ if (error instanceof ZeroXKeyError ||
295
+ error instanceof ZeroXKeyNetworkError) {
296
+ callbacks?.onError?.(error);
297
+ }
298
+ else {
299
+ callbacks?.onError?.(new ZeroXKeyError("Failed to clear session timeouts", ZeroXKeyErrorCodes.CLEAR_SESSION_TIMEOUTS_ERROR, error));
300
+ }
301
+ }
302
+ }
303
+ /**
304
+ * Initializes the user sessions by fetching all active sessions and setting up their state.
305
+ * @internal
306
+ */
307
+ const initializeSessions = async () => {
308
+ setSession(undefined);
309
+ setAllSessions(undefined);
310
+ try {
311
+ const allLocalStorageSessions = await getAllSessions();
312
+ if (!allLocalStorageSessions)
313
+ return;
314
+ await Promise.all(Object.keys(allLocalStorageSessions).map(async (sessionKey) => {
315
+ const s = allLocalStorageSessions?.[sessionKey];
316
+ if (!isValidSession(s)) {
317
+ await clearSession({ sessionKey });
318
+ if (sessionKey === (await getActiveSessionKey())) {
319
+ setSession(undefined);
320
+ }
321
+ delete allLocalStorageSessions[sessionKey];
322
+ return;
323
+ }
324
+ await scheduleSessionExpiration({
325
+ sessionKey,
326
+ expiry: s.expiry,
327
+ });
328
+ }));
329
+ setAllSessions(allLocalStorageSessions || undefined);
330
+ const activeSessionKey = await client?.getActiveSessionKey();
331
+ if (activeSessionKey) {
332
+ if (!allLocalStorageSessions[activeSessionKey]) {
333
+ return;
334
+ }
335
+ setSession(allLocalStorageSessions[activeSessionKey]);
336
+ await maybeRefreshUser();
337
+ await maybeRefreshWallets();
338
+ return;
339
+ }
340
+ }
341
+ catch (error) {
342
+ if (error instanceof ZeroXKeyError ||
343
+ error instanceof ZeroXKeyNetworkError) {
344
+ callbacks?.onError?.(error);
345
+ }
346
+ else {
347
+ callbacks?.onError?.(new ZeroXKeyError(`Failed to initialize sessions`, ZeroXKeyErrorCodes.INITIALIZE_SESSION_ERROR, error));
348
+ }
349
+ }
350
+ };
351
+ /**
352
+ * @internal
353
+ * Handles the post-authentication flow.
354
+ *
355
+ * - This function is called after a successful authentication (login or sign-up) via any supported method (Passkey, Wallet, OTP, OAuth).
356
+ * - It fetches the active session and all sessions, updates the session state, and schedules session expiration and warning timeouts.
357
+ * - It also refreshes the user's wallets and profile information to ensure the provider state is up to date.
358
+ * - This function is used internally after all authentication flows to synchronize state and trigger any necessary callbacks.
359
+ *
360
+ * @returns A void promise.
361
+ * @throws {ZeroXKeyError} If the client is not initialized or if there is an error during the process.
362
+ */
363
+ const handlePostAuth = async (params) => {
364
+ const { method, action, identifier } = params;
365
+ try {
366
+ const sessionKey = await getActiveSessionKey();
367
+ const session = await getSession({
368
+ ...(sessionKey && { sessionKey }),
369
+ });
370
+ if (session && sessionKey)
371
+ await scheduleSessionExpiration({
372
+ sessionKey,
373
+ expiry: session.expiry,
374
+ });
375
+ const allSessions = await client.getAllSessions();
376
+ setSession(session);
377
+ setAllSessions(allSessions);
378
+ await maybeRefreshWallets();
379
+ await maybeRefreshUser();
380
+ callbacks?.onAuthenticationSuccess?.({
381
+ session,
382
+ method,
383
+ action,
384
+ identifier,
385
+ });
386
+ }
387
+ catch (error) {
388
+ if (error instanceof ZeroXKeyError ||
389
+ error instanceof ZeroXKeyNetworkError) {
390
+ callbacks?.onError?.(error);
391
+ }
392
+ else {
393
+ callbacks?.onError?.(new ZeroXKeyError(`Failed to handle post-authentication`, ZeroXKeyErrorCodes.HANDLE_POST_AUTH_ERROR, error));
394
+ }
395
+ }
396
+ };
397
+ /**
398
+ * @internal
399
+ * Handles the post-logout flow.
400
+ *
401
+ * - This function is called after a successful logout or session clear.
402
+ * - It clears all scheduled session expiration and warning timeouts associated to the session key to prevent memory leaks.
403
+ * - It resets the session state, removes user data from memory, the logged out session from all sessions state, and clears the wallets list.
404
+ * - This ensures that all sensitive information is removed from the provider state after logout.
405
+ * - Called internally after logout or when all sessions are cleared.
406
+ *
407
+ * @returns void
408
+ * @throws {ZeroXKeyError} If there is an error during the post-logout process.
409
+ */
410
+ const handlePostLogout = (sessionKey) => {
411
+ try {
412
+ clearSessionTimeouts(sessionKey ? [sessionKey, `${sessionKey}-warning`] : undefined);
413
+ setAllSessions((prev) => {
414
+ if (!prev)
415
+ return prev;
416
+ if (sessionKey) {
417
+ const next = { ...prev };
418
+ delete next[sessionKey];
419
+ return next;
420
+ }
421
+ return {};
422
+ });
423
+ setSession(undefined);
424
+ setUser(undefined);
425
+ setWallets([]);
426
+ }
427
+ catch (error) {
428
+ callbacks?.onError?.(new ZeroXKeyError(`Failed to initialize sessions`, ZeroXKeyErrorCodes.HANDLE_POST_LOGOUT_ERROR, error));
429
+ }
430
+ };
431
+ const createPasskey = useCallback(async (params) => {
432
+ if (!client) {
433
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
434
+ }
435
+ return withZeroXKeyErrorHandling(() => client.createPasskey({ ...params }), () => logout(), callbacks, "Failed to create passkey");
436
+ }, [client, callbacks]);
437
+ const createHttpClient = useCallback((params) => {
438
+ if (!client) {
439
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
440
+ }
441
+ return client.createHttpClient(params);
442
+ }, [client]);
443
+ const logout = useCallback(async (params) => {
444
+ if (!client) {
445
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
446
+ }
447
+ await withZeroXKeyErrorHandling(async () => {
448
+ // If no sessionKey is provided, we try to get the active one.
449
+ let sessionKey = params?.sessionKey;
450
+ if (!sessionKey)
451
+ sessionKey = await getActiveSessionKey();
452
+ await client.logout(params);
453
+ // We only handle post logout if the sessionKey is defined since that means we actually logged out of a session.
454
+ if (sessionKey)
455
+ handlePostLogout(sessionKey);
456
+ }, () => logout(), callbacks, "Failed to logout");
457
+ return;
458
+ }, [client, callbacks]);
459
+ const loginWithPasskey = useCallback(async (params) => {
460
+ if (!client) {
461
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
462
+ }
463
+ const expirationSeconds = params?.expirationSeconds ??
464
+ masterConfig?.auth?.sessionExpirationSeconds ??
465
+ DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
466
+ const res = await withZeroXKeyErrorHandling(() => client.loginWithPasskey({ ...params, expirationSeconds }), () => logout(), callbacks, "Failed to login with passkey");
467
+ if (res) {
468
+ await handlePostAuth({
469
+ method: AuthMethod.Passkey,
470
+ action: AuthAction.LOGIN,
471
+ identifier: res.credentialId,
472
+ });
473
+ }
474
+ return res;
475
+ }, [client, callbacks]);
476
+ const signUpWithPasskey = useCallback(async (params) => {
477
+ if (!client) {
478
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
479
+ }
480
+ if (!masterConfig) {
481
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
482
+ }
483
+ // If createSubOrgParams is not provided, use the default from masterConfig
484
+ let createSubOrgParams = params?.createSubOrgParams ??
485
+ masterConfig.auth?.createSuborgParams?.passkeyAuth;
486
+ params =
487
+ createSubOrgParams !== undefined
488
+ ? { ...params, createSubOrgParams }
489
+ : { ...params };
490
+ const expirationSeconds = params.expirationSeconds ??
491
+ masterConfig?.auth?.sessionExpirationSeconds ??
492
+ DEFAULT_SESSION_EXPIRATION_IN_SECONDS;
493
+ const websiteName = Platform.OS === "web" && typeof window !== "undefined"
494
+ ? window.location.hostname
495
+ : DeviceInfo.getApplicationName() ||
496
+ DeviceInfo.getBundleId() ||
497
+ "mobile-app";
498
+ const timestamp = new Date().toLocaleDateString() +
499
+ "-" +
500
+ new Date().toLocaleTimeString([], {
501
+ hour: "2-digit",
502
+ minute: "2-digit",
503
+ });
504
+ // We allow passkeyName to be passed in thru the provider or thru the params of this function directly.
505
+ // This is because signUpWithPasskey will create a new passkey using that name.
506
+ // Any extra authenticators will be created after the first one. (see core implementation)
507
+ const passkeyName = params?.passkeyDisplayName ??
508
+ masterConfig.auth?.createSuborgParams?.passkeyAuth?.passkeyName ??
509
+ `${websiteName}-${timestamp}`;
510
+ const res = await withZeroXKeyErrorHandling(() => client.signUpWithPasskey({
511
+ ...params,
512
+ passkeyDisplayName: passkeyName,
513
+ expirationSeconds,
514
+ }), () => logout(), callbacks, "Failed to sign up with passkey");
515
+ if (res) {
516
+ await handlePostAuth({
517
+ method: AuthMethod.Passkey,
518
+ action: AuthAction.SIGNUP,
519
+ identifier: res.credentialId,
520
+ });
521
+ }
522
+ return res;
523
+ }, [client, callbacks]);
524
+ const initOtp = useCallback(async (params) => {
525
+ if (!client) {
526
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
527
+ }
528
+ return withZeroXKeyErrorHandling(() => client.initOtp(params), () => logout(), callbacks, "Failed to initialize OTP");
529
+ }, [client, callbacks]);
530
+ const verifyOtp = useCallback(async (params) => {
531
+ if (!client) {
532
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
533
+ }
534
+ return withZeroXKeyErrorHandling(() => client.verifyOtp(params), () => logout(), callbacks, "Failed to verify OTP");
535
+ }, [client, callbacks]);
536
+ const loginWithOtp = useCallback(async (params) => {
537
+ if (!client) {
538
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
539
+ }
540
+ const res = await withZeroXKeyErrorHandling(() => client.loginWithOtp(params), () => logout(), callbacks, "Failed to login with OTP");
541
+ if (res) {
542
+ await handlePostAuth({
543
+ method: AuthMethod.Otp,
544
+ action: AuthAction.LOGIN,
545
+ identifier: params.verificationToken,
546
+ });
547
+ }
548
+ return res;
549
+ }, [client, callbacks]);
550
+ const signUpWithOtp = useCallback(async (params) => {
551
+ if (!client) {
552
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
553
+ }
554
+ if (!masterConfig) {
555
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
556
+ }
557
+ // If createSubOrgParams is not provided, use the default from masterConfig
558
+ let createSubOrgParams = params.createSubOrgParams;
559
+ if (!createSubOrgParams && masterConfig?.auth?.createSuborgParams) {
560
+ if (params.otpType === OtpType.Email) {
561
+ createSubOrgParams =
562
+ masterConfig.auth.createSuborgParams.emailOtpAuth;
563
+ }
564
+ else if (params.otpType === OtpType.Sms) {
565
+ createSubOrgParams = masterConfig.auth.createSuborgParams.smsOtpAuth;
566
+ }
567
+ }
568
+ params =
569
+ createSubOrgParams !== undefined
570
+ ? { ...params, createSubOrgParams }
571
+ : { ...params };
572
+ const res = await withZeroXKeyErrorHandling(() => client.signUpWithOtp(params), () => logout(), callbacks, "Failed to sign up with OTP");
573
+ if (res) {
574
+ await handlePostAuth({
575
+ method: AuthMethod.Otp,
576
+ action: AuthAction.SIGNUP,
577
+ identifier: params.verificationToken,
578
+ });
579
+ }
580
+ return res;
581
+ }, [client, callbacks, masterConfig]);
582
+ const completeOtp = useCallback(async (params) => {
583
+ if (!client) {
584
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
585
+ }
586
+ if (!masterConfig) {
587
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
588
+ }
589
+ // If createSubOrgParams is not provided, use the default from masterConfig
590
+ let createSubOrgParams = params.createSubOrgParams;
591
+ if (!createSubOrgParams && masterConfig?.auth?.createSuborgParams) {
592
+ if (params.otpType === OtpType.Email) {
593
+ createSubOrgParams =
594
+ masterConfig.auth.createSuborgParams.emailOtpAuth;
595
+ }
596
+ else if (params.otpType === OtpType.Sms) {
597
+ createSubOrgParams = masterConfig.auth.createSuborgParams.smsOtpAuth;
598
+ }
599
+ }
600
+ params =
601
+ createSubOrgParams !== undefined
602
+ ? { ...params, createSubOrgParams }
603
+ : { ...params };
604
+ const res = await withZeroXKeyErrorHandling(() => client.completeOtp(params), () => logout(), callbacks, "Failed to complete OTP");
605
+ if (res) {
606
+ await handlePostAuth({
607
+ method: AuthMethod.Otp,
608
+ action: res.action,
609
+ identifier: res.verificationToken,
610
+ });
611
+ }
612
+ return res;
613
+ }, [client, callbacks, masterConfig]);
614
+ const loginWithOauth = useCallback(async (params) => {
615
+ if (!client) {
616
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
617
+ }
618
+ const res = await withZeroXKeyErrorHandling(() => client.loginWithOauth(params), () => logout(), callbacks, "Failed to login with OAuth");
619
+ if (res) {
620
+ await handlePostAuth({
621
+ method: AuthMethod.Oauth,
622
+ action: AuthAction.LOGIN,
623
+ identifier: params.oidcToken,
624
+ });
625
+ }
626
+ return res;
627
+ }, [client, callbacks]);
628
+ const signUpWithOauth = useCallback(async (params) => {
629
+ if (!client) {
630
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
631
+ }
632
+ if (!masterConfig) {
633
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
634
+ }
635
+ // If createSubOrgParams is not provided, use the default from masterConfig
636
+ let createSubOrgParams = params.createSubOrgParams ??
637
+ masterConfig.auth?.createSuborgParams?.oauth;
638
+ params =
639
+ createSubOrgParams !== undefined
640
+ ? { ...params, createSubOrgParams }
641
+ : { ...params };
642
+ const res = await withZeroXKeyErrorHandling(() => client.signUpWithOauth(params), () => logout(), callbacks, "Failed to sign up with OAuth");
643
+ if (res) {
644
+ await handlePostAuth({
645
+ method: AuthMethod.Oauth,
646
+ action: AuthAction.SIGNUP,
647
+ identifier: params.oidcToken,
648
+ });
649
+ }
650
+ return res;
651
+ }, [client, callbacks, masterConfig]);
652
+ const completeOauth = useCallback(async (params) => {
653
+ if (!client) {
654
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
655
+ }
656
+ if (!masterConfig) {
657
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
658
+ }
659
+ // If createSubOrgParams is not provided, use the default from masterConfig
660
+ const createSubOrgParams = params.createSubOrgParams ??
661
+ masterConfig.auth?.createSuborgParams?.oauth;
662
+ params =
663
+ createSubOrgParams !== undefined
664
+ ? { ...params, createSubOrgParams }
665
+ : { ...params };
666
+ const res = await withZeroXKeyErrorHandling(() => client.completeOauth(params), () => logout(), callbacks, "Failed to complete OAuth");
667
+ if (res) {
668
+ await handlePostAuth({
669
+ method: AuthMethod.Oauth,
670
+ action: res.action,
671
+ identifier: params.oidcToken,
672
+ });
673
+ }
674
+ return res;
675
+ }, [client, callbacks, masterConfig]);
676
+ const fetchWallets = useCallback(async (params) => {
677
+ if (!client) {
678
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
679
+ }
680
+ return withZeroXKeyErrorHandling(() => client.fetchWallets(params), () => logout(), callbacks, "Failed to fetch wallets");
681
+ }, [client, callbacks]);
682
+ const fetchWalletAccounts = useCallback(async (params) => {
683
+ if (!client) {
684
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
685
+ }
686
+ return withZeroXKeyErrorHandling(() => client.fetchWalletAccounts(params), () => logout(), callbacks, "Failed to fetch wallet accounts");
687
+ }, [client, callbacks]);
688
+ const fetchPrivateKeys = useCallback(async (params) => {
689
+ if (!client) {
690
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
691
+ }
692
+ return withZeroXKeyErrorHandling(() => client.fetchPrivateKeys(params), () => logout(), callbacks, "Failed to fetch private keys");
693
+ }, [client, callbacks]);
694
+ const fetchBootProofForAppProof = useCallback(async (params) => {
695
+ if (!client)
696
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
697
+ return withZeroXKeyErrorHandling(() => client.fetchBootProofForAppProof(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
698
+ }, [client, callbacks]);
699
+ const signMessage = useCallback(async (params) => {
700
+ if (!client)
701
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
702
+ return withZeroXKeyErrorHandling(() => client.signMessage(params), () => logout(), callbacks, "Failed to sign message");
703
+ }, [client, callbacks]);
704
+ const signTransaction = useCallback(async (params) => {
705
+ if (!client)
706
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
707
+ return withZeroXKeyErrorHandling(() => client.signTransaction(params), () => logout(), callbacks, "Failed to sign transaction");
708
+ }, [client, callbacks]);
709
+ const solSendTransaction = useCallback(async (params) => {
710
+ if (!client)
711
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
712
+ return withZeroXKeyErrorHandling(() => client.solSendTransaction(params), () => logout(), callbacks, "Failed to send sol transaction");
713
+ }, [client, callbacks]);
714
+ const ethSendTransaction = useCallback(async (params) => {
715
+ if (!client)
716
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
717
+ return withZeroXKeyErrorHandling(() => client.ethSendTransaction(params), () => logout(), callbacks, "Failed to send eth transaction");
718
+ }, [client, callbacks]);
719
+ const ethSendErc20Transfer = useCallback(async (params) => {
720
+ if (!client)
721
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
722
+ return withZeroXKeyErrorHandling(() => client.ethSendErc20Transfer(params), () => logout(), callbacks, "Failed to send ERC20 transfer");
723
+ }, [client, callbacks]);
724
+ const signAndSendTransaction = useCallback(async (params) => {
725
+ if (!client)
726
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
727
+ return withZeroXKeyErrorHandling(() => client.signAndSendTransaction(params), () => logout(), callbacks, "Failed to sign and send raw transaction");
728
+ }, [client, callbacks, logout]);
729
+ const pollTransactionStatus = useCallback(async (params) => {
730
+ if (!client)
731
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
732
+ return withZeroXKeyErrorHandling(() => client.pollTransactionStatus(params), () => logout(), callbacks, "Failed to poll transaction status");
733
+ }, [client, callbacks]);
734
+ const fetchUser = useCallback(async (params) => {
735
+ if (!client)
736
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
737
+ return withZeroXKeyErrorHandling(() => client.fetchUser(params), () => logout(), callbacks, "Failed to fetch user");
738
+ }, [client, callbacks]);
739
+ const fetchOrCreateP256ApiKeyUser = useCallback(async (params) => {
740
+ if (!client)
741
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
742
+ return withZeroXKeyErrorHandling(() => client.fetchOrCreateP256ApiKeyUser(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
743
+ }, [client, callbacks]);
744
+ const fetchOrCreatePolicies = useCallback(async (params) => {
745
+ if (!client)
746
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
747
+ return withZeroXKeyErrorHandling(() => client.fetchOrCreatePolicies(params), () => logout(), callbacks, "Failed to fetch or create delegated access user");
748
+ }, [client, callbacks]);
749
+ const updateUserEmail = useCallback(async (params) => {
750
+ if (!client)
751
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
752
+ const res = await withZeroXKeyErrorHandling(() => client.updateUserEmail(params), () => logout(), callbacks, "Failed to update user email");
753
+ if (res)
754
+ await maybeRefreshUser({
755
+ stampWith: params?.stampWith,
756
+ ...(params?.organizationId && {
757
+ organizationId: params.organizationId,
758
+ }),
759
+ ...(params?.userId && { userId: params.userId }),
760
+ });
761
+ return res;
762
+ }, [client, callbacks]);
763
+ const removeUserEmail = useCallback(async (params) => {
764
+ if (!client)
765
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
766
+ const res = await withZeroXKeyErrorHandling(() => client.removeUserEmail(params), () => logout(), callbacks, "Failed to remove user email");
767
+ if (res)
768
+ await maybeRefreshUser({
769
+ stampWith: params?.stampWith,
770
+ ...(params?.organizationId && {
771
+ organizationId: params.organizationId,
772
+ }),
773
+ ...(params?.userId && { userId: params.userId }),
774
+ });
775
+ return res;
776
+ }, [client, callbacks]);
777
+ const updateUserPhoneNumber = useCallback(async (params) => {
778
+ if (!client)
779
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
780
+ const res = await withZeroXKeyErrorHandling(() => client.updateUserPhoneNumber(params), () => logout(), callbacks, "Failed to update user phone number");
781
+ if (res)
782
+ await maybeRefreshUser({
783
+ stampWith: params?.stampWith,
784
+ ...(params?.organizationId && {
785
+ organizationId: params.organizationId,
786
+ }),
787
+ ...(params?.userId && { userId: params.userId }),
788
+ });
789
+ return res;
790
+ }, [client, callbacks]);
791
+ const removeUserPhoneNumber = useCallback(async (params) => {
792
+ if (!client)
793
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
794
+ const res = await withZeroXKeyErrorHandling(() => client.removeUserPhoneNumber(params), () => logout(), callbacks, "Failed to remove user phone number");
795
+ if (res)
796
+ await maybeRefreshUser({
797
+ stampWith: params?.stampWith,
798
+ ...(params?.organizationId && {
799
+ organizationId: params.organizationId,
800
+ }),
801
+ ...(params?.userId && { userId: params.userId }),
802
+ });
803
+ return res;
804
+ }, [client, callbacks]);
805
+ const updateUserName = useCallback(async (params) => {
806
+ if (!client)
807
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
808
+ const res = await withZeroXKeyErrorHandling(() => client.updateUserName(params), () => logout(), callbacks, "Failed to update user name");
809
+ if (res)
810
+ await maybeRefreshUser({
811
+ stampWith: params?.stampWith,
812
+ ...(params?.organizationId && {
813
+ organizationId: params.organizationId,
814
+ }),
815
+ ...(params?.userId && { userId: params.userId }),
816
+ });
817
+ return res;
818
+ }, [client, callbacks]);
819
+ const addOauthProvider = useCallback(async (params) => {
820
+ if (!client)
821
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
822
+ const res = await withZeroXKeyErrorHandling(() => client.addOauthProvider(params), () => logout(), callbacks, "Failed to add OAuth provider");
823
+ if (res)
824
+ await maybeRefreshUser({
825
+ stampWith: params?.stampWith,
826
+ ...(params?.organizationId && {
827
+ organizationId: params.organizationId,
828
+ }),
829
+ ...(params?.userId && { userId: params.userId }),
830
+ });
831
+ return res;
832
+ }, [client, callbacks]);
833
+ const removeOauthProviders = useCallback(async (params) => {
834
+ if (!client)
835
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
836
+ const res = await withZeroXKeyErrorHandling(() => client.removeOauthProviders(params), () => logout(), callbacks, "Failed to remove OAuth providers");
837
+ if (res)
838
+ await maybeRefreshUser({
839
+ stampWith: params?.stampWith,
840
+ ...(params?.organizationId && {
841
+ organizationId: params.organizationId,
842
+ }),
843
+ ...(params?.userId && { userId: params.userId }),
844
+ });
845
+ return res;
846
+ }, [client, callbacks]);
847
+ const addPasskey = useCallback(async (params) => {
848
+ if (!client)
849
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
850
+ const res = await withZeroXKeyErrorHandling(() => client.addPasskey(params), () => logout(), callbacks, "Failed to add passkey");
851
+ if (res)
852
+ await maybeRefreshUser({
853
+ stampWith: params?.stampWith,
854
+ ...(params?.organizationId && {
855
+ organizationId: params.organizationId,
856
+ }),
857
+ ...(params?.userId && { userId: params.userId }),
858
+ });
859
+ return res;
860
+ }, [client, callbacks]);
861
+ const removePasskeys = useCallback(async (params) => {
862
+ if (!client)
863
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
864
+ const res = await withZeroXKeyErrorHandling(() => client.removePasskeys(params), () => logout(), callbacks, "Failed to remove passkeys");
865
+ if (res)
866
+ await maybeRefreshUser({
867
+ stampWith: params?.stampWith,
868
+ ...(params?.organizationId && {
869
+ organizationId: params.organizationId,
870
+ }),
871
+ ...(params?.userId && { userId: params.userId }),
872
+ });
873
+ return res;
874
+ }, [client, callbacks]);
875
+ const createWallet = useCallback(async (params) => {
876
+ if (!client)
877
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
878
+ const res = await withZeroXKeyErrorHandling(() => client.createWallet(params), () => logout(), callbacks, "Failed to create wallet");
879
+ const s = await getSession();
880
+ if (res && s)
881
+ await maybeRefreshWallets({
882
+ stampWith: params?.stampWith,
883
+ ...(params?.organizationId && {
884
+ organizationId: params.organizationId,
885
+ }),
886
+ });
887
+ return res;
888
+ }, [client, session, callbacks]);
889
+ const createWalletAccounts = useCallback(async (params) => {
890
+ if (!client)
891
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
892
+ const res = await withZeroXKeyErrorHandling(() => client.createWalletAccounts(params), () => logout(), callbacks, "Failed to create wallet accounts");
893
+ const s = await getSession();
894
+ if (res && s)
895
+ await maybeRefreshWallets({
896
+ stampWith: params?.stampWith,
897
+ ...(params?.organizationId && {
898
+ organizationId: params.organizationId,
899
+ }),
900
+ });
901
+ return res;
902
+ }, [client, session, callbacks]);
903
+ const exportWallet = useCallback(async (params) => {
904
+ if (!client)
905
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
906
+ // Default: decrypt unless explicitly disabled
907
+ const shouldDecrypt = params?.decrypt !== false;
908
+ if (!shouldDecrypt) {
909
+ const res = await withZeroXKeyErrorHandling(() => client.exportWallet({
910
+ walletId: params.walletId,
911
+ targetPublicKey: params.targetPublicKey,
912
+ ...(params.organizationId && {
913
+ organizationId: params.organizationId,
914
+ }),
915
+ ...(params.stampWith && { stampWith: params.stampWith }),
916
+ }), () => logout(), callbacks, "Failed to export wallet");
917
+ const s = await getSession();
918
+ if (res && s)
919
+ await maybeRefreshWallets({
920
+ stampWith: params?.stampWith,
921
+ ...(params?.organizationId && {
922
+ organizationId: params.organizationId,
923
+ }),
924
+ });
925
+ return res;
926
+ }
927
+ // Decrypting path: generate P-256 keypair, export, then decrypt to mnemonic
928
+ try {
929
+ const { privateKey, publicKeyUncompressed } = generateP256KeyPair();
930
+ const targetPublicKey = publicKeyUncompressed;
931
+ const exportParams = {
932
+ walletId: params.walletId,
933
+ targetPublicKey,
934
+ ...(params.organizationId && {
935
+ organizationId: params.organizationId,
936
+ }),
937
+ ...(params.stampWith && { stampWith: params.stampWith }),
938
+ };
939
+ const bundle = await withZeroXKeyErrorHandling(() => client.exportWallet(exportParams), () => logout(), callbacks, "Failed to export wallet");
940
+ const session = await getSession();
941
+ const orgId = session?.organizationId;
942
+ if (!orgId) {
943
+ throw new ZeroXKeyError("Missing organizationId in session for decryption", ZeroXKeyErrorCodes.INVALID_REQUEST);
944
+ }
945
+ const mnemonic = await decryptExportBundle({
946
+ exportBundle: bundle,
947
+ embeddedKey: privateKey,
948
+ organizationId: orgId,
949
+ returnMnemonic: true,
950
+ keyFormat: "HEXADECIMAL",
951
+ });
952
+ return mnemonic;
953
+ }
954
+ catch (error) {
955
+ throw error;
956
+ }
957
+ }, [client, session, callbacks]);
958
+ const exportPrivateKey = useCallback(async (params) => {
959
+ if (!client)
960
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
961
+ const shouldDecrypt = params?.decrypt !== false;
962
+ if (!shouldDecrypt) {
963
+ const res = await withZeroXKeyErrorHandling(() => client.exportPrivateKey({
964
+ privateKeyId: params.privateKeyId,
965
+ targetPublicKey: params.targetPublicKey,
966
+ ...(params.organizationId && {
967
+ organizationId: params.organizationId,
968
+ }),
969
+ ...(params.stampWith && { stampWith: params.stampWith }),
970
+ }), () => logout(), callbacks, "Failed to export private key");
971
+ return res;
972
+ }
973
+ try {
974
+ const { privateKey, publicKeyUncompressed } = generateP256KeyPair();
975
+ const targetPublicKey = publicKeyUncompressed;
976
+ const exportParams = {
977
+ privateKeyId: params.privateKeyId,
978
+ targetPublicKey,
979
+ ...(params.organizationId && {
980
+ organizationId: params.organizationId,
981
+ }),
982
+ ...(params.stampWith && { stampWith: params.stampWith }),
983
+ };
984
+ const bundle = await withZeroXKeyErrorHandling(() => client.exportPrivateKey(exportParams), () => logout(), callbacks, "Failed to export private key");
985
+ const session = await getSession();
986
+ const orgId = session?.organizationId;
987
+ if (!orgId) {
988
+ throw new ZeroXKeyError("Missing organizationId in session for decryption", ZeroXKeyErrorCodes.INVALID_REQUEST);
989
+ }
990
+ const rawPrivateKey = await decryptExportBundle({
991
+ exportBundle: bundle,
992
+ embeddedKey: privateKey,
993
+ organizationId: orgId,
994
+ returnMnemonic: false,
995
+ keyFormat: "HEXADECIMAL",
996
+ });
997
+ return rawPrivateKey;
998
+ }
999
+ catch (error) {
1000
+ throw error;
1001
+ }
1002
+ }, [client, callbacks]);
1003
+ const exportWalletAccount = useCallback(async (params) => {
1004
+ if (!client)
1005
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1006
+ const shouldDecrypt = params?.decrypt !== false;
1007
+ if (!shouldDecrypt) {
1008
+ const res = await withZeroXKeyErrorHandling(() => client.exportWalletAccount({
1009
+ address: params.address,
1010
+ targetPublicKey: params.targetPublicKey,
1011
+ ...(params.organizationId && {
1012
+ organizationId: params.organizationId,
1013
+ }),
1014
+ ...(params.stampWith && { stampWith: params.stampWith }),
1015
+ }), () => logout(), callbacks, "Failed to export wallet accounts");
1016
+ return res;
1017
+ }
1018
+ try {
1019
+ const { privateKey, publicKeyUncompressed } = generateP256KeyPair();
1020
+ const targetPublicKey = publicKeyUncompressed;
1021
+ const exportParams = {
1022
+ address: params.address,
1023
+ targetPublicKey,
1024
+ ...(params.organizationId && {
1025
+ organizationId: params.organizationId,
1026
+ }),
1027
+ ...(params.stampWith && { stampWith: params.stampWith }),
1028
+ };
1029
+ const bundle = await withZeroXKeyErrorHandling(() => client.exportWalletAccount(exportParams), () => logout(), callbacks, "Failed to export wallet accounts");
1030
+ const session = await getSession();
1031
+ const orgId = session?.organizationId;
1032
+ if (!orgId) {
1033
+ throw new ZeroXKeyError("Missing organizationId in session for decryption", ZeroXKeyErrorCodes.INVALID_REQUEST);
1034
+ }
1035
+ const decryptedKey = await decryptExportBundle({
1036
+ exportBundle: bundle,
1037
+ embeddedKey: privateKey,
1038
+ organizationId: orgId,
1039
+ returnMnemonic: false,
1040
+ keyFormat: "HEXADECIMAL",
1041
+ });
1042
+ return decryptedKey;
1043
+ }
1044
+ catch (error) {
1045
+ throw error;
1046
+ }
1047
+ }, [client, callbacks, masterConfig, session, user]);
1048
+ const importWallet = useCallback(async (params) => {
1049
+ if (!client)
1050
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1051
+ const { mnemonic, walletName, accounts, organizationId, userId, stampWith, } = params;
1052
+ // Resolve org/user from params or current session
1053
+ const currentSession = await getSession();
1054
+ const effectiveOrgId = organizationId ?? currentSession?.organizationId;
1055
+ const effectiveUserId = userId ?? currentSession?.userId;
1056
+ if (!effectiveOrgId || !effectiveUserId) {
1057
+ throw new ZeroXKeyError("Missing organizationId or userId for wallet import", ZeroXKeyErrorCodes.INVALID_REQUEST);
1058
+ }
1059
+ // Step 1: init import to obtain importBundle
1060
+ const initRes = await withZeroXKeyErrorHandling(() => client.httpClient?.initImportWallet({
1061
+ organizationId: effectiveOrgId,
1062
+ userId: effectiveUserId,
1063
+ }, stampWith), () => logout(), callbacks, "Failed to init wallet import");
1064
+ const importBundle = initRes?.importBundle;
1065
+ if (!importBundle) {
1066
+ throw new ZeroXKeyError("Failed to retrieve import bundle", ZeroXKeyErrorCodes.IMPORT_WALLET_ERROR);
1067
+ }
1068
+ // Step 2: encrypt mnemonic to encryptedBundle
1069
+ const encryptedBundle = await encryptWalletToBundle({
1070
+ mnemonic,
1071
+ importBundle,
1072
+ userId: effectiveUserId,
1073
+ organizationId: effectiveOrgId,
1074
+ });
1075
+ // Step 3: call importWallet with encrypted bundle
1076
+ const res = await withZeroXKeyErrorHandling(() => client.importWallet({
1077
+ encryptedBundle,
1078
+ walletName,
1079
+ ...(accounts && { accounts }),
1080
+ organizationId: effectiveOrgId,
1081
+ userId: effectiveUserId,
1082
+ ...(stampWith && { stampWith }),
1083
+ }), () => logout(), callbacks, "Failed to import wallet");
1084
+ // Refresh state after import
1085
+ if (res)
1086
+ await maybeRefreshWallets({
1087
+ ...(stampWith && { stampWith }),
1088
+ organizationId: effectiveOrgId,
1089
+ userId: effectiveUserId,
1090
+ });
1091
+ return res;
1092
+ }, [client, callbacks, masterConfig, session, user]);
1093
+ const importPrivateKey = useCallback(async (params) => {
1094
+ if (!client)
1095
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1096
+ const { privateKey, privateKeyName, addressFormats, curve, keyFormat = "HEXADECIMAL", organizationId, userId, stampWith, } = params;
1097
+ // Resolve org/user
1098
+ const currentSession = await getSession();
1099
+ const effectiveOrgId = organizationId ?? currentSession?.organizationId;
1100
+ const effectiveUserId = userId ?? currentSession?.userId;
1101
+ if (!effectiveOrgId || !effectiveUserId) {
1102
+ throw new ZeroXKeyError("Missing organizationId or userId for private key import", ZeroXKeyErrorCodes.INVALID_REQUEST);
1103
+ }
1104
+ // Init import to get bundle
1105
+ const initRes = await withZeroXKeyErrorHandling(() => client.httpClient?.initImportPrivateKey({
1106
+ organizationId: effectiveOrgId,
1107
+ userId: effectiveUserId,
1108
+ }, stampWith), () => logout(), callbacks, "Failed to init private key import");
1109
+ const importBundle = initRes?.importBundle;
1110
+ if (!importBundle) {
1111
+ throw new ZeroXKeyError("Failed to retrieve import bundle", ZeroXKeyErrorCodes.IMPORT_WALLET_ERROR);
1112
+ }
1113
+ // Encrypt provided private key to bundle
1114
+ const encryptedBundle = await encryptPrivateKeyToBundle({
1115
+ privateKey,
1116
+ keyFormat,
1117
+ importBundle,
1118
+ userId: effectiveUserId,
1119
+ organizationId: effectiveOrgId,
1120
+ });
1121
+ // Import
1122
+ const res = await withZeroXKeyErrorHandling(() => client.importPrivateKey({
1123
+ encryptedBundle,
1124
+ privateKeyName,
1125
+ addressFormats,
1126
+ curve: curve ?? "CURVE_SECP256K1",
1127
+ organizationId: effectiveOrgId,
1128
+ userId: effectiveUserId,
1129
+ ...(stampWith && { stampWith }),
1130
+ }), () => logout(), callbacks, "Failed to import private key");
1131
+ return res;
1132
+ }, [client, callbacks, masterConfig, session, user]);
1133
+ const deleteSubOrganization = useCallback(async (params) => {
1134
+ if (!client)
1135
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1136
+ return withZeroXKeyErrorHandling(() => client.deleteSubOrganization(params), () => logout(), callbacks, "Failed to delete sub-organization");
1137
+ }, [client, callbacks, masterConfig, session, user]);
1138
+ const storeSession = useCallback(async (params) => {
1139
+ if (!client)
1140
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1141
+ await withZeroXKeyErrorHandling(() => client.storeSession(params), () => logout(), callbacks, "Failed to store session");
1142
+ const sessionKey = await getActiveSessionKey();
1143
+ const session = await getSession({
1144
+ ...(sessionKey && { sessionKey }),
1145
+ });
1146
+ if (session && sessionKey)
1147
+ await scheduleSessionExpiration({ sessionKey, expiry: session.expiry });
1148
+ const allSessions = await getAllSessions();
1149
+ setSession(session);
1150
+ setAllSessions(allSessions);
1151
+ await maybeRefreshWallets();
1152
+ await maybeRefreshUser();
1153
+ }, [client, callbacks, masterConfig, session, user]);
1154
+ const clearSession = useCallback(async (params) => {
1155
+ if (!client)
1156
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1157
+ await withZeroXKeyErrorHandling(async () => client.clearSession(params), () => logout(), callbacks, "Failed to clear session");
1158
+ const sessionKey = params?.sessionKey ?? (await getActiveSessionKey());
1159
+ if (!sessionKey)
1160
+ return;
1161
+ if (!params?.sessionKey) {
1162
+ setSession(undefined);
1163
+ }
1164
+ clearSessionTimeouts([sessionKey]);
1165
+ // clear only the cleared session from allSessions
1166
+ const newAllSessions = { ...allSessions };
1167
+ if (newAllSessions) {
1168
+ delete newAllSessions[sessionKey];
1169
+ }
1170
+ setAllSessions(newAllSessions);
1171
+ return;
1172
+ }, [client, callbacks, session, user, masterConfig]);
1173
+ const clearAllSessions = useCallback(async () => {
1174
+ if (!client)
1175
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1176
+ setSession(undefined);
1177
+ setAllSessions(undefined);
1178
+ clearSessionTimeouts();
1179
+ return await withZeroXKeyErrorHandling(() => client.clearAllSessions(), () => logout(), callbacks, "Failed to clear all sessions");
1180
+ }, [client, callbacks, session, user, masterConfig]);
1181
+ const refreshSession = useCallback(async (params) => {
1182
+ if (!client) {
1183
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1184
+ }
1185
+ const activeSessionKey = await client.getActiveSessionKey();
1186
+ if (!activeSessionKey) {
1187
+ throw new ZeroXKeyError("No active session found.", ZeroXKeyErrorCodes.NO_SESSION_FOUND);
1188
+ }
1189
+ const sessionKey = params?.sessionKey ?? activeSessionKey;
1190
+ const res = await withZeroXKeyErrorHandling(() => client.refreshSession({ ...params }), () => logout(), callbacks, "Failed to refresh session");
1191
+ const session = await getSession({ sessionKey });
1192
+ if (session && sessionKey) {
1193
+ await scheduleSessionExpiration({
1194
+ sessionKey,
1195
+ expiry: session.expiry,
1196
+ ...(params?.expirationSeconds && {
1197
+ expirationSeconds: params?.expirationSeconds,
1198
+ }),
1199
+ });
1200
+ }
1201
+ const allSessions = await getAllSessions();
1202
+ setSession(session);
1203
+ setAllSessions(allSessions);
1204
+ return res;
1205
+ }, [client, callbacks, scheduleSessionExpiration, session, user, masterConfig]);
1206
+ const getSession = useCallback(async (params) => {
1207
+ if (!client)
1208
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1209
+ return withZeroXKeyErrorHandling(() => client.getSession(params), () => logout(), callbacks, "Failed to get session");
1210
+ }, [client, callbacks, masterConfig, session, user]);
1211
+ const getAllSessions = useCallback(async () => {
1212
+ if (!client)
1213
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1214
+ return withZeroXKeyErrorHandling(() => client.getAllSessions(), () => logout(), callbacks, "Failed to get all sessions");
1215
+ }, [client, callbacks, masterConfig, session, user]);
1216
+ const setActiveSession = useCallback(async (params) => {
1217
+ if (!client)
1218
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1219
+ const session = await withZeroXKeyErrorHandling(() => client.getSession({ sessionKey: params.sessionKey }), () => logout(), callbacks, "Failed to get session");
1220
+ const s = await getSession();
1221
+ if (!s) {
1222
+ throw new ZeroXKeyError("Session not found.", ZeroXKeyErrorCodes.NOT_FOUND);
1223
+ }
1224
+ await withZeroXKeyErrorHandling(() => client.setActiveSession(params), () => logout(), callbacks, "Failed to set active session");
1225
+ setSession(session);
1226
+ await withZeroXKeyErrorHandling(async () => {
1227
+ await maybeRefreshWallets();
1228
+ await maybeRefreshUser();
1229
+ }, () => logout(), callbacks, "Failed to refresh data after setting active session");
1230
+ return;
1231
+ }, [client, callbacks, session, user, masterConfig]);
1232
+ const getActiveSessionKey = useCallback(async () => {
1233
+ if (!client)
1234
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1235
+ return withZeroXKeyErrorHandling(() => client.getActiveSessionKey(), () => logout(), callbacks, "Failed to get active session key");
1236
+ }, [client, callbacks, masterConfig, session, user]);
1237
+ const clearUnusedKeyPairs = useCallback(async () => {
1238
+ if (!client)
1239
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1240
+ return withZeroXKeyErrorHandling(() => client.clearUnusedKeyPairs(), () => logout(), callbacks, "Failed to clear unused key pairs");
1241
+ }, [client, callbacks, masterConfig, session, user]);
1242
+ const createApiKeyPair = useCallback(async (params) => {
1243
+ if (!client)
1244
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1245
+ return withZeroXKeyErrorHandling(() => client.createApiKeyPair(params), () => logout(), callbacks, "Failed to create API key pair");
1246
+ }, [client, callbacks, session, user, masterConfig]);
1247
+ const getProxyAuthConfig = useCallback(async () => {
1248
+ if (!client)
1249
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1250
+ return withZeroXKeyErrorHandling(() => client.getProxyAuthConfig(), () => logout(), callbacks, "Failed to get proxy auth config");
1251
+ }, [client, callbacks, masterConfig, session, user]);
1252
+ const verifyAppProofs = useCallback(async (params) => {
1253
+ if (!client)
1254
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1255
+ return withZeroXKeyErrorHandling(() => client.verifyAppProofs(params), () => logout(), callbacks, "Failed to verify app proofs");
1256
+ }, [client, callbacks]);
1257
+ const refreshUser = useCallback(async (params) => {
1258
+ const { stampWith, organizationId, userId } = params || {};
1259
+ if (!client)
1260
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1261
+ const user = await withZeroXKeyErrorHandling(() => fetchUser({
1262
+ stampWith,
1263
+ ...(organizationId && { organizationId }),
1264
+ ...(userId && { userId }),
1265
+ }), () => logout(), callbacks, "Failed to refresh user");
1266
+ if (user) {
1267
+ setUser(user);
1268
+ }
1269
+ }, [client, callbacks, fetchUser, session, user]);
1270
+ /**
1271
+ * @internal
1272
+ * Auto-refresh user only if enabled in config. This is only used internally.
1273
+ *
1274
+ * @param params.organizationId - organization ID to specify the sub-organization (defaults to the current session's organizationId).
1275
+ * @param params.userId - user ID to fetch specific user details (defaults to the current session's userId).
1276
+ * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
1277
+ * @returns A promise that resolves when the user is refreshed, or does nothing if auto-refresh is disabled
1278
+ */
1279
+ const maybeRefreshUser = useCallback(async (params) => {
1280
+ if (!masterConfig?.autoRefreshManagedState)
1281
+ return;
1282
+ return refreshUser(params);
1283
+ }, [masterConfig, refreshUser]);
1284
+ const refreshWallets = useCallback(async (params) => {
1285
+ const { stampWith, organizationId, userId } = params || {};
1286
+ if (!client)
1287
+ throw new ZeroXKeyError("Client is not initialized.", ZeroXKeyErrorCodes.CLIENT_NOT_INITIALIZED);
1288
+ const wallets = await withZeroXKeyErrorHandling(() => fetchWallets({
1289
+ stampWith,
1290
+ ...(organizationId && { organizationId }),
1291
+ ...(userId && { userId }),
1292
+ }), () => logout(), callbacks, "Failed to refresh wallets");
1293
+ if (wallets) {
1294
+ setWallets(wallets);
1295
+ }
1296
+ return wallets;
1297
+ }, [client, callbacks, fetchWallets, session, user]);
1298
+ /**
1299
+ * @internal
1300
+ * Auto-refresh wallets only if enabled in config. This is only used internally.
1301
+ *
1302
+ * @param params.organizationId - organization ID to specify the sub-organization (defaults to the current session's organizationId).
1303
+ * @param params.userId - user ID to fetch specific user details (defaults to the current session's userId).
1304
+ * @param params.stampWith - parameter to stamp the request with a specific stamper (StamperType.Passkey, StamperType.ApiKey, or StamperType.Wallet).
1305
+ * @returns A promise that resolves to an array of wallets, or an empty array if auto-refresh is disabled
1306
+ */
1307
+ const maybeRefreshWallets = useCallback(async (params) => {
1308
+ if (!masterConfig?.autoRefreshManagedState)
1309
+ return [];
1310
+ return refreshWallets(params);
1311
+ }, [masterConfig, refreshWallets]);
1312
+ const handleDiscordOauth = useCallback(async (params) => {
1313
+ const { additionalState: additionalParameters } = params || {};
1314
+ const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(OAuthProviders.DISCORD);
1315
+ try {
1316
+ if (!masterConfig) {
1317
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1318
+ }
1319
+ if (!clientId) {
1320
+ throw new ZeroXKeyError("Discord Client ID is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1321
+ }
1322
+ if (!redirectUri) {
1323
+ throw new ZeroXKeyError("OAuth Redirect URI is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1324
+ }
1325
+ if (!scheme) {
1326
+ throw new ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1327
+ }
1328
+ // Create key pair and generate nonce
1329
+ const publicKey = await createApiKeyPair();
1330
+ if (!publicKey) {
1331
+ throw new ZeroXKeyError("Failed to create public key for OAuth.", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1332
+ }
1333
+ const nonce = bytesToHex(sha256(publicKey));
1334
+ // Generate PKCE challenge pair and store verifier
1335
+ const { verifier, codeChallenge } = await generateChallengePair();
1336
+ await storePKCEVerifier(OAuthProviders.DISCORD, verifier);
1337
+ // Build OAuth URL (direct Discord URL, not proxy)
1338
+ const discordAuthUrl = buildOAuthUrl({
1339
+ provider: OAuthProviders.DISCORD,
1340
+ clientId,
1341
+ redirectUri,
1342
+ publicKey,
1343
+ nonce,
1344
+ codeChallenge,
1345
+ additionalState: additionalParameters,
1346
+ useOauthProxyOrigin: false,
1347
+ });
1348
+ if (!(await InAppBrowser.isAvailable())) {
1349
+ throw new ZeroXKeyError("InAppBrowser is not available", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1350
+ }
1351
+ const result = await InAppBrowser.openAuth(discordAuthUrl, scheme, {
1352
+ dismissButtonStyle: "cancel",
1353
+ animated: true,
1354
+ modalPresentationStyle: "fullScreen",
1355
+ modalTransitionStyle: "coverVertical",
1356
+ modalEnabled: true,
1357
+ enableBarCollapsing: false,
1358
+ showTitle: true,
1359
+ enableUrlBarHiding: true,
1360
+ enableDefaultShare: true,
1361
+ });
1362
+ if (!result || result.type !== "success" || !result.url) {
1363
+ throw new ZeroXKeyError("OAuth flow did not complete successfully", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1364
+ }
1365
+ // Parse the deep link result
1366
+ const parsed = parseInAppBrowserResult(result.url);
1367
+ if (!parsed.authCode) {
1368
+ throw new ZeroXKeyError("Missing authorization code from Discord OAuth", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1369
+ }
1370
+ // Handle PKCE flow: exchange code for token and complete
1371
+ await handlePKCEFlow({
1372
+ provider: OAuthProviders.DISCORD,
1373
+ publicKey,
1374
+ authCode: parsed.authCode,
1375
+ ...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
1376
+ ...(callbacks && { callbacks }),
1377
+ completeOauth,
1378
+ exchangeCodeForToken: async (codeVerifier) => {
1379
+ const resp = await client?.httpClient?.proxyOAuth2Authenticate({
1380
+ provider: "OAUTH2_PROVIDER_DISCORD",
1381
+ authCode: parsed.authCode,
1382
+ redirectUri,
1383
+ codeVerifier,
1384
+ clientId,
1385
+ nonce,
1386
+ });
1387
+ const oidcToken = resp?.oidcToken;
1388
+ if (!oidcToken) {
1389
+ throw new ZeroXKeyError("Missing oidcToken from OAuth exchange", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1390
+ }
1391
+ return oidcToken;
1392
+ },
1393
+ });
1394
+ return;
1395
+ }
1396
+ catch (error) {
1397
+ throw error;
1398
+ }
1399
+ }, [client, callbacks, masterConfig, session, user]);
1400
+ const handleXOauth = useCallback(async (params) => {
1401
+ const { additionalState: additionalParameters } = params || {};
1402
+ const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(OAuthProviders.X);
1403
+ try {
1404
+ if (!masterConfig) {
1405
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1406
+ }
1407
+ if (!clientId) {
1408
+ throw new ZeroXKeyError("Twitter Client ID is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1409
+ }
1410
+ if (!redirectUri) {
1411
+ throw new ZeroXKeyError("OAuth Redirect URI is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1412
+ }
1413
+ if (!scheme) {
1414
+ throw new ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1415
+ }
1416
+ const publicKey = await createApiKeyPair();
1417
+ if (!publicKey) {
1418
+ throw new ZeroXKeyError("Failed to create public key for OAuth.", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1419
+ }
1420
+ const nonce = bytesToHex(sha256(publicKey));
1421
+ // Generate PKCE challenge pair and store verifier
1422
+ const { verifier, codeChallenge } = await generateChallengePair();
1423
+ await storePKCEVerifier(OAuthProviders.X, verifier);
1424
+ // Build OAuth URL (direct X/Twitter URL, not proxy)
1425
+ const twitterAuthUrl = buildOAuthUrl({
1426
+ provider: OAuthProviders.X,
1427
+ clientId,
1428
+ redirectUri,
1429
+ publicKey,
1430
+ nonce,
1431
+ codeChallenge,
1432
+ additionalState: additionalParameters,
1433
+ useOauthProxyOrigin: false,
1434
+ });
1435
+ if (!(await InAppBrowser.isAvailable())) {
1436
+ throw new ZeroXKeyError("InAppBrowser is not available", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1437
+ }
1438
+ const result = await InAppBrowser.openAuth(twitterAuthUrl, scheme, {
1439
+ dismissButtonStyle: "cancel",
1440
+ animated: true,
1441
+ modalPresentationStyle: "fullScreen",
1442
+ modalTransitionStyle: "coverVertical",
1443
+ modalEnabled: true,
1444
+ enableBarCollapsing: false,
1445
+ showTitle: true,
1446
+ enableUrlBarHiding: true,
1447
+ enableDefaultShare: true,
1448
+ });
1449
+ if (!result || result.type !== "success" || !result.url) {
1450
+ throw new ZeroXKeyError("OAuth flow did not complete successfully", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1451
+ }
1452
+ // Parse the deep link result
1453
+ const parsed = parseInAppBrowserResult(result.url);
1454
+ if (!parsed.authCode) {
1455
+ throw new ZeroXKeyError("Missing authorization code from Twitter OAuth", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1456
+ }
1457
+ // Handle PKCE flow: exchange code for token and complete
1458
+ await handlePKCEFlow({
1459
+ provider: OAuthProviders.X,
1460
+ publicKey,
1461
+ authCode: parsed.authCode,
1462
+ ...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
1463
+ ...(callbacks && { callbacks }),
1464
+ completeOauth,
1465
+ exchangeCodeForToken: async (codeVerifier) => {
1466
+ const resp = await client?.httpClient?.proxyOAuth2Authenticate({
1467
+ provider: "OAUTH2_PROVIDER_X",
1468
+ authCode: parsed.authCode,
1469
+ redirectUri,
1470
+ codeVerifier,
1471
+ clientId,
1472
+ nonce,
1473
+ });
1474
+ const oidcToken = resp?.oidcToken;
1475
+ if (!oidcToken) {
1476
+ throw new ZeroXKeyError("Missing oidcToken from OAuth exchange", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1477
+ }
1478
+ return oidcToken;
1479
+ },
1480
+ });
1481
+ return;
1482
+ }
1483
+ catch (error) {
1484
+ throw error;
1485
+ }
1486
+ }, [client, callbacks, masterConfig, session, user]);
1487
+ const handleGoogleOauth = useCallback(async (params) => {
1488
+ const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(OAuthProviders.GOOGLE);
1489
+ try {
1490
+ if (!masterConfig) {
1491
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1492
+ }
1493
+ if (!clientId) {
1494
+ throw new ZeroXKeyError("Google Client ID is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1495
+ }
1496
+ if (!redirectUri) {
1497
+ throw new ZeroXKeyError("OAuth Redirect URI is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1498
+ }
1499
+ if (!scheme) {
1500
+ throw new ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1501
+ }
1502
+ const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
1503
+ // Create key pair and generate nonce
1504
+ const publicKey = await createApiKeyPair();
1505
+ if (!publicKey) {
1506
+ throw new ZeroXKeyError("Failed to create public key for OAuth.", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1507
+ }
1508
+ const nonce = bytesToHex(sha256(publicKey));
1509
+ // Build OAuth URL using ZeroXKey OAuth proxy
1510
+ const oauthUrl = buildOAuthUrl({
1511
+ provider: OAuthProviders.GOOGLE,
1512
+ clientId,
1513
+ redirectUri: finalRedirectUri,
1514
+ publicKey,
1515
+ nonce,
1516
+ useOauthProxyOrigin: true,
1517
+ });
1518
+ if (!(await InAppBrowser.isAvailable())) {
1519
+ throw new ZeroXKeyError("InAppBrowser is not available", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1520
+ }
1521
+ const result = await InAppBrowser.openAuth(oauthUrl, scheme, {
1522
+ dismissButtonStyle: "cancel",
1523
+ animated: true,
1524
+ modalPresentationStyle: "fullScreen",
1525
+ modalTransitionStyle: "coverVertical",
1526
+ modalEnabled: true,
1527
+ enableBarCollapsing: false,
1528
+ showTitle: true,
1529
+ enableUrlBarHiding: true,
1530
+ enableDefaultShare: true,
1531
+ });
1532
+ if (!result || result.type !== "success" || !result.url) {
1533
+ throw new ZeroXKeyError("OAuth flow did not complete successfully", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1534
+ }
1535
+ // Parse the deep link result
1536
+ const parsed = parseInAppBrowserResult(result.url);
1537
+ if (!parsed.idToken) {
1538
+ throw new ZeroXKeyError("oidcToken not found in the response", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1539
+ }
1540
+ // Complete OAuth flow
1541
+ await completeOAuthFlow({
1542
+ provider: OAuthProviders.GOOGLE,
1543
+ publicKey,
1544
+ oidcToken: parsed.idToken,
1545
+ ...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
1546
+ ...(callbacks && { callbacks }),
1547
+ completeOauth,
1548
+ });
1549
+ return;
1550
+ }
1551
+ catch (error) {
1552
+ throw error;
1553
+ }
1554
+ }, [client, callbacks, masterConfig, session, user]);
1555
+ const handleAppleOauth = useCallback(async (params) => {
1556
+ const { additionalState: additionalParameters } = params || {};
1557
+ const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(OAuthProviders.APPLE);
1558
+ try {
1559
+ if (!masterConfig) {
1560
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1561
+ }
1562
+ if (!clientId) {
1563
+ throw new ZeroXKeyError("Apple Client ID is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1564
+ }
1565
+ if (!redirectUri) {
1566
+ throw new ZeroXKeyError("OAuth Redirect URI is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1567
+ }
1568
+ if (!scheme) {
1569
+ throw new ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1570
+ }
1571
+ const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
1572
+ // Create key pair and generate nonce
1573
+ const publicKey = await createApiKeyPair();
1574
+ if (!publicKey) {
1575
+ throw new ZeroXKeyError("Failed to create public key for OAuth.", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1576
+ }
1577
+ const nonce = bytesToHex(sha256(publicKey));
1578
+ // Build OAuth URL using ZeroXKey OAuth proxy
1579
+ const oauthUrl = buildOAuthUrl({
1580
+ provider: OAuthProviders.APPLE,
1581
+ clientId,
1582
+ redirectUri: finalRedirectUri,
1583
+ publicKey,
1584
+ nonce,
1585
+ additionalState: additionalParameters,
1586
+ useOauthProxyOrigin: true,
1587
+ });
1588
+ if (!(await InAppBrowser.isAvailable())) {
1589
+ throw new ZeroXKeyError("InAppBrowser is not available", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1590
+ }
1591
+ const result = await InAppBrowser.openAuth(oauthUrl, scheme, {
1592
+ dismissButtonStyle: "cancel",
1593
+ animated: true,
1594
+ modalPresentationStyle: "fullScreen",
1595
+ modalTransitionStyle: "coverVertical",
1596
+ modalEnabled: true,
1597
+ enableBarCollapsing: false,
1598
+ showTitle: true,
1599
+ enableUrlBarHiding: true,
1600
+ enableDefaultShare: true,
1601
+ });
1602
+ if (!result || result.type !== "success" || !result.url) {
1603
+ throw new ZeroXKeyError("OAuth flow did not complete successfully", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1604
+ }
1605
+ // Parse the deep link result
1606
+ const parsed = parseInAppBrowserResult(result.url);
1607
+ if (!parsed.idToken) {
1608
+ throw new ZeroXKeyError("oidcToken not found in the response", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1609
+ }
1610
+ // Complete OAuth flow
1611
+ await completeOAuthFlow({
1612
+ provider: OAuthProviders.APPLE,
1613
+ publicKey,
1614
+ oidcToken: parsed.idToken,
1615
+ ...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
1616
+ ...(callbacks && { callbacks }),
1617
+ completeOauth,
1618
+ });
1619
+ return;
1620
+ }
1621
+ catch (error) {
1622
+ throw error;
1623
+ }
1624
+ }, [client, callbacks, masterConfig, session, user]);
1625
+ const handleFacebookOauth = useCallback(async (params) => {
1626
+ const { additionalState: additionalParameters } = params || {};
1627
+ const { clientId, redirectUri, appScheme: scheme, } = getOauthProviderSettings(OAuthProviders.FACEBOOK);
1628
+ try {
1629
+ if (!masterConfig) {
1630
+ throw new ZeroXKeyError("Config is not ready yet!", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1631
+ }
1632
+ if (!clientId) {
1633
+ throw new ZeroXKeyError("Facebook Client ID is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1634
+ }
1635
+ if (!redirectUri) {
1636
+ throw new ZeroXKeyError("OAuth Redirect URI is not configured.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1637
+ }
1638
+ if (!scheme) {
1639
+ throw new ZeroXKeyError("Missing appScheme. Please set auth.oauth.appScheme.", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1640
+ }
1641
+ const finalRedirectUri = `${redirectUri}?scheme=${encodeURIComponent(scheme)}`;
1642
+ // Create key pair and generate nonce
1643
+ const publicKey = await createApiKeyPair();
1644
+ if (!publicKey) {
1645
+ throw new ZeroXKeyError("Failed to create public key for OAuth.", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1646
+ }
1647
+ const nonce = bytesToHex(sha256(publicKey));
1648
+ // Generate PKCE challenge pair and store verifier
1649
+ const { verifier, codeChallenge } = await generateChallengePair();
1650
+ await storePKCEVerifier(OAuthProviders.FACEBOOK, verifier);
1651
+ // Build OAuth URL using ZeroXKey OAuth proxy
1652
+ const oauthUrl = buildOAuthUrl({
1653
+ provider: OAuthProviders.FACEBOOK,
1654
+ clientId,
1655
+ redirectUri: finalRedirectUri,
1656
+ publicKey,
1657
+ nonce,
1658
+ codeChallenge,
1659
+ additionalState: additionalParameters,
1660
+ useOauthProxyOrigin: true,
1661
+ });
1662
+ if (!(await InAppBrowser.isAvailable())) {
1663
+ throw new ZeroXKeyError("InAppBrowser is not available", ZeroXKeyErrorCodes.INVALID_CONFIGURATION);
1664
+ }
1665
+ const result = await InAppBrowser.openAuth(oauthUrl, scheme, {
1666
+ dismissButtonStyle: "cancel",
1667
+ animated: true,
1668
+ modalPresentationStyle: "fullScreen",
1669
+ modalTransitionStyle: "coverVertical",
1670
+ modalEnabled: true,
1671
+ enableBarCollapsing: false,
1672
+ showTitle: true,
1673
+ enableUrlBarHiding: true,
1674
+ enableDefaultShare: true,
1675
+ });
1676
+ if (!result || result.type !== "success" || !result.url) {
1677
+ throw new ZeroXKeyError("OAuth flow did not complete successfully", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1678
+ }
1679
+ // Parse the deep link result
1680
+ const parsed = parseInAppBrowserResult(result.url);
1681
+ if (!parsed.authCode) {
1682
+ throw new ZeroXKeyError("Missing authorization code from Facebook OAuth", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1683
+ }
1684
+ // Handle PKCE flow: exchange code for token and complete
1685
+ await handlePKCEFlow({
1686
+ provider: OAuthProviders.FACEBOOK,
1687
+ publicKey,
1688
+ authCode: parsed.authCode,
1689
+ ...(parsed.sessionKey && { sessionKey: parsed.sessionKey }),
1690
+ ...(callbacks && { callbacks }),
1691
+ completeOauth,
1692
+ exchangeCodeForToken: async (codeVerifier) => {
1693
+ const tokenData = await exchangeCodeForToken(clientId, finalRedirectUri, parsed.authCode, codeVerifier);
1694
+ const idToken = tokenData?.id_token;
1695
+ if (!idToken) {
1696
+ throw new ZeroXKeyError("Missing oidcToken from OAuth exchange", ZeroXKeyErrorCodes.OAUTH_SIGNUP_ERROR);
1697
+ }
1698
+ return idToken;
1699
+ },
1700
+ });
1701
+ return;
1702
+ }
1703
+ catch (error) {
1704
+ throw error;
1705
+ }
1706
+ }, [client, callbacks, masterConfig, session, user]);
1707
+ useEffect(() => {
1708
+ if (proxyAuthConfigRef.current)
1709
+ return;
1710
+ // Only fetch the proxy auth config once. Use that to build the master config.
1711
+ const fetchProxyAuthConfig = async () => {
1712
+ try {
1713
+ let proxyAuthConfig;
1714
+ if (shouldFetchWalletKitConfig) {
1715
+ // Only fetch the proxy auth config if we have an authProxyId and the autoFetchWalletKitConfig param is enabled or not passed in.
1716
+ const sanitizedAuthProxyUrl = config.authProxyUrl && config.authProxyUrl.trim()
1717
+ ? config.authProxyUrl
1718
+ : undefined;
1719
+ proxyAuthConfig = await getAuthProxyConfig(config.authProxyConfigId, // Can assert safely. See shouldFetchWalletKitConfig definition.
1720
+ sanitizedAuthProxyUrl);
1721
+ proxyAuthConfigRef.current = proxyAuthConfig;
1722
+ }
1723
+ setMasterConfig(buildConfig(proxyAuthConfig));
1724
+ }
1725
+ catch {
1726
+ setClientState(ClientState.Error);
1727
+ }
1728
+ };
1729
+ fetchProxyAuthConfig();
1730
+ }, []);
1731
+ useEffect(() => {
1732
+ // Start the client initialization process once we have the master config.
1733
+ if (!masterConfig)
1734
+ return;
1735
+ initializeClient();
1736
+ }, [masterConfig]);
1737
+ useEffect(() => {
1738
+ // Handle changes to the passed in config prop -- update the master config
1739
+ // Rebuild the master config with the updated config and stored proxyAuthConfig
1740
+ // If we don't have a stored proxyAuthConfig and we need to fetch it, we wait until that fetch is done in the other useEffect.
1741
+ // If shouldFetchWalletKitConfig is false, we'll never have a proxyAuthConfig to build the master config with, so this useEffect should always run.
1742
+ if (!proxyAuthConfigRef.current && shouldFetchWalletKitConfig)
1743
+ return;
1744
+ setMasterConfig(buildConfig(proxyAuthConfigRef.current ?? undefined));
1745
+ }, [config, proxyAuthConfigRef.current]);
1746
+ useEffect(() => {
1747
+ // authState must be consistent with session state. We found during testing that there are cases where the session and authState can be out of sync in very rare edge cases.
1748
+ // This will ensure that they are always in sync and remove the need to setAuthState manually in other places.
1749
+ if (session && isValidSession(session)) {
1750
+ setAuthState(AuthState.Authenticated);
1751
+ }
1752
+ else {
1753
+ setAuthState(AuthState.Unauthenticated);
1754
+ }
1755
+ }, [session]);
1756
+ useEffect(() => {
1757
+ // After client and config are ready, initialize sessions then mark client ready.
1758
+ if (!client || !masterConfig)
1759
+ return;
1760
+ clearSessionTimeouts();
1761
+ initializeSessions().finally(() => {
1762
+ setClientState(ClientState.Ready);
1763
+ });
1764
+ return () => {
1765
+ clearSessionTimeouts();
1766
+ };
1767
+ }, [client]);
1768
+ return (jsx(ClientContext.Provider, { value: {
1769
+ session,
1770
+ allSessions,
1771
+ clientState,
1772
+ authState,
1773
+ user,
1774
+ wallets,
1775
+ config: masterConfig,
1776
+ httpClient: client?.httpClient,
1777
+ createHttpClient,
1778
+ createPasskey,
1779
+ logout,
1780
+ loginWithPasskey,
1781
+ signUpWithPasskey,
1782
+ initOtp,
1783
+ verifyOtp,
1784
+ loginWithOtp,
1785
+ signUpWithOtp,
1786
+ completeOtp,
1787
+ loginWithOauth,
1788
+ signUpWithOauth,
1789
+ completeOauth,
1790
+ fetchWallets,
1791
+ fetchWalletAccounts,
1792
+ fetchPrivateKeys,
1793
+ verifyAppProofs,
1794
+ refreshWallets,
1795
+ signMessage,
1796
+ signTransaction,
1797
+ signAndSendTransaction,
1798
+ ethSendTransaction,
1799
+ ethSendErc20Transfer,
1800
+ solSendTransaction,
1801
+ pollTransactionStatus,
1802
+ fetchUser,
1803
+ fetchOrCreateP256ApiKeyUser,
1804
+ fetchOrCreatePolicies,
1805
+ refreshUser,
1806
+ updateUserEmail,
1807
+ removeUserEmail,
1808
+ updateUserPhoneNumber,
1809
+ removeUserPhoneNumber,
1810
+ updateUserName,
1811
+ addOauthProvider,
1812
+ removeOauthProviders,
1813
+ addPasskey,
1814
+ removePasskeys,
1815
+ createWallet,
1816
+ createWalletAccounts,
1817
+ exportWallet,
1818
+ exportPrivateKey,
1819
+ exportWalletAccount,
1820
+ importWallet,
1821
+ importPrivateKey,
1822
+ deleteSubOrganization,
1823
+ storeSession,
1824
+ clearSession,
1825
+ clearAllSessions,
1826
+ refreshSession,
1827
+ getSession,
1828
+ getAllSessions,
1829
+ setActiveSession,
1830
+ clearUnusedKeyPairs,
1831
+ getActiveSessionKey,
1832
+ createApiKeyPair,
1833
+ getProxyAuthConfig,
1834
+ handleGoogleOauth,
1835
+ handleXOauth,
1836
+ handleDiscordOauth,
1837
+ handleAppleOauth,
1838
+ handleFacebookOauth,
1839
+ fetchBootProofForAppProof,
1840
+ }, children: children }));
1841
+ };
1842
+
1843
+ export { ZeroXKeyProvider };
1844
+ //# sourceMappingURL=ZeroXKeyProvider.mjs.map