@naculus/connect-appkit-react 0.1.8 → 0.2.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 (94) hide show
  1. package/README.md +4 -4
  2. package/dist/client.cjs +1 -1
  3. package/dist/client.cjs.map +1 -1
  4. package/dist/client.d.cts +144 -0
  5. package/dist/client.d.ts +144 -0
  6. package/dist/client.js +1 -1
  7. package/dist/client.js.map +1 -1
  8. package/dist/index.cjs +2 -1
  9. package/dist/index.cjs.map +1 -1
  10. package/dist/index.d.cts +2270 -0
  11. package/dist/index.d.ts +2270 -0
  12. package/dist/index.js +2 -1
  13. package/dist/index.js.map +1 -1
  14. package/package.json +30 -12
  15. package/api-extractor.json +0 -21
  16. package/src/chain-abstraction/index.ts +0 -8
  17. package/src/chain-abstraction/useCompareCosts.ts +0 -137
  18. package/src/chain-abstraction/useExecuteRoute.ts +0 -129
  19. package/src/chain-abstraction/useRouteQuote.ts +0 -168
  20. package/src/client.test.ts +0 -242
  21. package/src/client.ts +0 -265
  22. package/src/hooks/useAccount.test.ts +0 -67
  23. package/src/hooks/useAccount.ts +0 -37
  24. package/src/hooks/useBalance.test.ts +0 -459
  25. package/src/hooks/useBalance.ts +0 -170
  26. package/src/hooks/useChain.test.ts +0 -160
  27. package/src/hooks/useChain.ts +0 -53
  28. package/src/hooks/useConnect.test.ts +0 -112
  29. package/src/hooks/useConnect.ts +0 -29
  30. package/src/hooks/useDisconnect.test.ts +0 -75
  31. package/src/hooks/useDisconnect.ts +0 -32
  32. package/src/hooks/useERC20Allowance.ts +0 -93
  33. package/src/hooks/useERC20Approve.ts +0 -220
  34. package/src/hooks/useERC20Transfer.ts +0 -134
  35. package/src/hooks/useERC20TransferSimulation.ts +0 -147
  36. package/src/hooks/useEmbeddedWallet.test.ts +0 -266
  37. package/src/hooks/useEmbeddedWallet.ts +0 -181
  38. package/src/hooks/useLastTx.test.ts +0 -117
  39. package/src/hooks/useLastTx.ts +0 -73
  40. package/src/hooks/useLookupAddress.ts +0 -131
  41. package/src/hooks/useNotification.ts +0 -308
  42. package/src/hooks/useResolveName.ts +0 -128
  43. package/src/hooks/useSIWxLogin.test.ts +0 -307
  44. package/src/hooks/useSIWxLogin.ts +0 -163
  45. package/src/hooks/useSIWxSession.test.ts +0 -481
  46. package/src/hooks/useSIWxSession.ts +0 -290
  47. package/src/hooks/useSendCalls.ts +0 -103
  48. package/src/hooks/useSendTransaction.test.ts +0 -175
  49. package/src/hooks/useSendTransaction.ts +0 -80
  50. package/src/hooks/useSendUserOperation.ts +0 -313
  51. package/src/hooks/useSession.ts +0 -96
  52. package/src/hooks/useSessionKeys.ts +0 -356
  53. package/src/hooks/useSignInWithEthereum.test.ts +0 -224
  54. package/src/hooks/useSignInWithEthereum.ts +0 -46
  55. package/src/hooks/useSignInWithX.test.ts +0 -210
  56. package/src/hooks/useSignInWithX.ts +0 -141
  57. package/src/hooks/useSignMessage.test.ts +0 -151
  58. package/src/hooks/useSignMessage.ts +0 -65
  59. package/src/hooks/useSimulateTransfer.ts +0 -165
  60. package/src/hooks/useSiwxAuthSession.test.ts +0 -456
  61. package/src/hooks/useSiwxAuthSession.ts +0 -163
  62. package/src/hooks/useSmartAccount.ts +0 -194
  63. package/src/hooks/useSwitchChain.ts +0 -68
  64. package/src/hooks/useTokenBalance.test.ts +0 -337
  65. package/src/hooks/useTokenBalance.ts +0 -210
  66. package/src/hooks/useTransactionSimulation.ts +0 -401
  67. package/src/hooks/useTxHistory.test.ts +0 -108
  68. package/src/hooks/useTxHistory.ts +0 -83
  69. package/src/hooks/useTxMonitor.test.ts +0 -127
  70. package/src/hooks/useTxMonitor.ts +0 -178
  71. package/src/hooks/useUserOpStatus.ts +0 -245
  72. package/src/hooks/useValidateDestination.test.ts +0 -96
  73. package/src/hooks/useValidateDestination.ts +0 -72
  74. package/src/hooks/useViemClient.test.ts +0 -155
  75. package/src/hooks/useViemClient.ts +0 -65
  76. package/src/hooks/useWallet.test.ts +0 -133
  77. package/src/hooks/useWallet.ts +0 -39
  78. package/src/hooks/useWeb3ErrorHandler.ts +0 -102
  79. package/src/index.ts +0 -186
  80. package/src/provider/Web3ConnectProvider.test.tsx +0 -178
  81. package/src/provider/Web3ConnectProvider.tsx +0 -530
  82. package/src/token-list/TokenSelector.tsx +0 -351
  83. package/src/token-list/defaults.ts +0 -39
  84. package/src/token-list/index.ts +0 -14
  85. package/src/token-list/useTokenList.ts +0 -119
  86. package/src/token-list/useTokenSearch.ts +0 -99
  87. package/src/types/index.ts +0 -99
  88. package/src/utils/chains.ts +0 -115
  89. package/src/utils/errorMessages.ts +0 -142
  90. package/src/utils/i18n.ts +0 -90
  91. package/src/wc-generated/components.ts +0 -377
  92. package/test/setup.ts +0 -17
  93. package/test/test-utils.tsx +0 -78
  94. package/tsup.config.ts +0 -18
@@ -1,530 +0,0 @@
1
- "use client";
2
-
3
- import React, { createContext, useContext, useReducer, useEffect, useCallback, useMemo, useRef } from "react";
4
- import type { UniversalWalletSession } from "@naculus/connect-core";
5
- import type { Web3State, Web3Actions, Web3ConnectConfig, ConnectionStatus, WalletChain } from "../types";
6
- import { createClient } from "../client";
7
- import { eip6963Connector } from "@naculus/connector-evm-injected";
8
- import {
9
- LocalStorageSessionStorage,
10
- WalletError,
11
- logger,
12
- SessionManager,
13
- createSessionManager,
14
- ConnectorManager,
15
- createConnectorManager,
16
- } from "@naculus/connect-core";
17
- import type { PocketConnectorClass as EmbeddedWalletConnectorClass } from "@naculus/connector-embedded";
18
- import { getDefaultChains } from "../utils/chains";
19
-
20
- // ── Timeout Helper ────────────────────────────────────────────────
21
-
22
- function withTimeout<T>(promise: Promise<T>, ms: number, label: string = "Operation"): Promise<T> {
23
- return Promise.race([
24
- promise,
25
- new Promise<T>((_, reject) =>
26
- setTimeout(() => reject(new Error(`${label} timed out after ${ms}ms`)), ms)
27
- ),
28
- ]);
29
- }
30
-
31
- // ── Retry Helper ──────────────────────────────────────────────────
32
-
33
- interface RetryOptions {
34
- maxRetries: number;
35
- baseDelay: number;
36
- label?: string;
37
- }
38
-
39
- async function withRetry<T>(fn: () => Promise<T>, options: RetryOptions): Promise<T> {
40
- let lastError: unknown;
41
- for (let attempt = 0; attempt <= options.maxRetries; attempt++) {
42
- try {
43
- return await fn();
44
- } catch (error) {
45
- lastError = error;
46
- if (attempt < options.maxRetries) {
47
- const delay = options.baseDelay * (2 ** attempt);
48
- logger.warn("react/provider", `Retry attempt ${attempt + 1}/${options.maxRetries} after ${delay}ms`);
49
- await new Promise((resolve) => setTimeout(resolve, delay));
50
- }
51
- }
52
- }
53
- throw lastError;
54
- }
55
-
56
- type Web3Action =
57
- | { type: "SET_STATUS"; payload: ConnectionStatus }
58
- | { type: "SET_SESSION"; payload: Web3State["session"] }
59
- | { type: "SET_ACCOUNTS"; payload: string[] }
60
- | { type: "SET_CHAIN"; payload: string | null }
61
- | { type: "SET_ERROR"; payload: Error | null }
62
- | { type: "RESET" };
63
-
64
- export interface Web3ContextValue extends Web3State, Web3Actions {
65
- isConnected: boolean;
66
- chains: WalletChain[];
67
- /** SessionManager instance for multi-chain session management */
68
- sessionManager: SessionManager | null;
69
- }
70
-
71
- const initialState: Web3State = {
72
- status: "disconnected",
73
- session: null,
74
- accounts: [],
75
- chainId: null,
76
- error: null
77
- };
78
-
79
- function web3Reducer(state: Web3State, action: Web3Action): Web3State {
80
- switch (action.type) {
81
- case "SET_STATUS":
82
- return { ...state, status: action.payload };
83
- case "SET_SESSION":
84
- return { ...state, session: action.payload };
85
- case "SET_ACCOUNTS":
86
- return { ...state, accounts: action.payload };
87
- case "SET_CHAIN":
88
- return { ...state, chainId: action.payload };
89
- case "SET_ERROR":
90
- return { ...state, error: action.payload };
91
- case "RESET":
92
- return initialState;
93
- default:
94
- return state;
95
- }
96
- }
97
-
98
- export const Web3Context = createContext<Web3ContextValue | null>(null);
99
-
100
- export interface Web3ConnectProviderProps {
101
- children: React.ReactNode;
102
- config: Web3ConnectConfig;
103
- autoConnect?: boolean;
104
- }
105
-
106
- export function Web3ConnectProvider({
107
- children,
108
- config,
109
- autoConnect = true
110
- }: Web3ConnectProviderProps) {
111
- const [state, dispatch] = useReducer(web3Reducer, initialState);
112
-
113
- const chains = useMemo(() => config.chains ?? getDefaultChains(), [config.chains]);
114
-
115
- const connectionTimeout = config.connectionTimeout ?? 30000;
116
- const maxRetries = config.maxRetries ?? 2;
117
-
118
- const storage = useMemo(
119
- () => new LocalStorageSessionStorage(config.storageKey ?? "naculus_web3_session"),
120
- [config.storageKey]
121
- );
122
-
123
- const client = useMemo(() => {
124
- return createClient({
125
- projectId: config.projectId,
126
- metadata: config.metadata,
127
- enableEmbedded: config.enableEmbedded,
128
- enablePasskeys: config.enablePasskeys,
129
- enableSolana: config.enableSolana,
130
- solanaDefaultChain: config.solanaDefaultChain,
131
- });
132
- }, [config.projectId, config.metadata, config.enableEmbedded, config.enablePasskeys, config.enableSolana, config.solanaDefaultChain]);
133
-
134
- // ── SessionManager ───────────────────────────────────────────────
135
-
136
- const sessionManagerRef = useRef<SessionManager | null>(null);
137
-
138
- const sessionManager = useMemo(() => {
139
- // Build a connector manager that shares the client's connectors
140
- const cm = createConnectorManager();
141
- cm.register(client.connector.id, client.connector);
142
-
143
- // Build default RPC/currency configs from the configured chains
144
- const defaultRpcUrls: Record<string, string> = {};
145
- const defaultCurrencies: Record<string, { name: string; symbol: string; decimals: number }> = {};
146
-
147
- for (const chain of chains) {
148
- const caip2Id = `${chain.namespace}:${chain.id}`;
149
- if (chain.rpcUrl) {
150
- defaultRpcUrls[caip2Id] = chain.rpcUrl;
151
- }
152
- if (chain.token) {
153
- defaultCurrencies[caip2Id] = {
154
- name: chain.name,
155
- symbol: chain.token,
156
- decimals: 18,
157
- };
158
- }
159
- }
160
-
161
- const sm = createSessionManager(cm, {
162
- autoRefreshFeeOnSwitch: true,
163
- defaultRpcUrls,
164
- defaultCurrencies,
165
- encryptionKey: config.encryptionKey,
166
- });
167
-
168
- sessionManagerRef.current = sm;
169
- return sm;
170
- }, [client, chains]);
171
-
172
- // Sync SessionManager events to provider state
173
- useEffect(() => {
174
- const onConnected = (payload: { bundle: any }) => {
175
- const { walletSession } = payload.bundle;
176
- dispatch({ type: "SET_SESSION", payload: walletSession });
177
-
178
- const accounts: string[] = [];
179
- Object.values(walletSession.namespaces).forEach((ns: any) => {
180
- accounts.push(...ns.accounts);
181
- });
182
- dispatch({ type: "SET_ACCOUNTS", payload: accounts });
183
- dispatch({ type: "SET_CHAIN", payload: payload.bundle.activeChainId });
184
- dispatch({ type: "SET_STATUS", payload: "connected" });
185
- };
186
-
187
- const onDisconnected = () => {
188
- dispatch({ type: "RESET" });
189
- };
190
-
191
- const onChainChanged = (payload: { newChainId: string }) => {
192
- dispatch({ type: "SET_CHAIN", payload: payload.newChainId });
193
- };
194
-
195
- sessionManager.on("sessionConnected", onConnected);
196
- sessionManager.on("sessionDisconnected", onDisconnected);
197
- sessionManager.on("chainChanged", onChainChanged);
198
-
199
- return () => {
200
- sessionManager.off("sessionConnected", onConnected);
201
- sessionManager.off("sessionDisconnected", onDisconnected);
202
- sessionManager.off("chainChanged", onChainChanged);
203
- };
204
- }, [sessionManager]);
205
-
206
- useEffect(() => {
207
- const handler = () => {
208
- storage.clear();
209
- dispatch({ type: "RESET" });
210
- };
211
- client.connector.onSessionExpiry(handler);
212
- }, [client, storage]);
213
-
214
- const updateStateFromSession = useCallback((session: typeof state.session) => {
215
- dispatch({ type: "SET_SESSION", payload: session });
216
-
217
- if (session) {
218
- const accounts: string[] = [];
219
- Object.values(session.namespaces).forEach((ns) => {
220
- accounts.push(...ns.accounts);
221
- });
222
- dispatch({ type: "SET_ACCOUNTS", payload: accounts });
223
-
224
- const evmChain = session.namespaces["eip155"]?.chains?.[0];
225
- const solChain = session.namespaces["solana"]?.chains?.[0];
226
- const xrplChain = session.namespaces["xrpl"]?.chains?.[0];
227
- dispatch({ type: "SET_CHAIN", payload: evmChain ?? solChain ?? xrplChain ?? null });
228
- } else {
229
- dispatch({ type: "SET_ACCOUNTS", payload: [] });
230
- dispatch({ type: "SET_CHAIN", payload: null });
231
- }
232
- }, []);
233
-
234
- // ── SIWx post-connection helper ──────────────────────────────────
235
- // Run after any connect method succeeds. Returns false if SIWx is
236
- // configured, required, and failed — the caller should abort without
237
- // setting status to "connected".
238
- const runSiwx = useCallback(async (session: UniversalWalletSession | null): Promise<boolean> => {
239
- if (!config.siwx || !session) return true;
240
-
241
- dispatch({ type: "SET_STATUS", payload: "authenticating" });
242
-
243
- try {
244
- const firstEvm = session.namespaces["eip155"]?.accounts?.[0];
245
- const firstSol = session.namespaces["solana"]?.accounts?.[0];
246
- const rawAddress = firstEvm ?? firstSol;
247
- if (!rawAddress) throw new WalletError("siwx_error", "No account found in session");
248
-
249
- const chainId = firstEvm
250
- ? session.namespaces["eip155"].chains?.[0] ?? "eip155:1"
251
- : session.namespaces["solana"].chains?.[0] ?? "solana:0";
252
-
253
- const address = rawAddress.includes(":") ? rawAddress.split(":").pop()! : rawAddress;
254
-
255
- const message = await config.siwx.createMessage({ address, chainId });
256
- const signature = (await client.signMessage(session, {
257
- message,
258
- address,
259
- chainId,
260
- })) as string;
261
-
262
- if (config.siwx.handleSignComplete) {
263
- await config.siwx.handleSignComplete({ message, signature });
264
- }
265
-
266
- return true;
267
- } catch (siwxError) {
268
- logger.error("react/provider", "SIWx authentication failed:", siwxError);
269
-
270
- if (config.siwx.required !== false) {
271
- await storage.clear();
272
- dispatch({ type: "RESET" });
273
- dispatch({
274
- type: "SET_ERROR",
275
- payload: siwxError instanceof Error ? siwxError : new Error("Wallet authentication failed"),
276
- });
277
- return false;
278
- }
279
-
280
- return true;
281
- }
282
- }, [config.siwx, client, storage]);
283
-
284
- const connect = useCallback(async (): Promise<void> => {
285
- dispatch({ type: "SET_STATUS", payload: "connecting" });
286
- dispatch({ type: "SET_ERROR", payload: null });
287
-
288
- try {
289
- const session = await withTimeout(
290
- client.connect(),
291
- connectionTimeout,
292
- "Wallet connect"
293
- );
294
- await storage.save(session);
295
- updateStateFromSession(session);
296
-
297
- // Feed the session into SessionManager
298
- try {
299
- const sm = sessionManagerRef.current;
300
- if (sm && session.walletType) {
301
- const evmChain = session.namespaces["eip155"]?.chains?.[0];
302
- const chainId = evmChain ?? "eip155:1";
303
- // Trigger SessionManager to build bundle from this session
304
- sm.connect(session.walletType, chainId);
305
- }
306
- } catch (smError) {
307
- logger.warn("react/provider", "SessionManager sync error:", smError);
308
- }
309
-
310
- if (!await runSiwx(session)) return;
311
- dispatch({ type: "SET_STATUS", payload: "connected" });
312
- } catch (error) {
313
- const message = error instanceof Error ? error.message : "Connection failed";
314
- dispatch({ type: "SET_ERROR", payload: error instanceof Error ? error : new Error(message) });
315
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
316
- }
317
- }, [client, storage, updateStateFromSession, connectionTimeout, runSiwx]);
318
-
319
- const connectEmbedded = useCallback(async (): Promise<void> => {
320
- dispatch({ type: "SET_STATUS", payload: "connecting" });
321
- dispatch({ type: "SET_ERROR", payload: null });
322
-
323
- try {
324
- const session = await client.connectEmbedded();
325
- await storage.save(session);
326
- updateStateFromSession(session);
327
- if (!await runSiwx(session)) return;
328
- dispatch({ type: "SET_STATUS", payload: "connected" });
329
- } catch (error) {
330
- const message = error instanceof Error ? error.message : "Embedded wallet connection failed";
331
- dispatch({ type: "SET_ERROR", payload: error instanceof Error ? error : new Error(message) });
332
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
333
- }
334
- }, [client, storage, updateStateFromSession, runSiwx]);
335
-
336
- const connectPasskeys = useCallback(async (): Promise<void> => {
337
- dispatch({ type: "SET_STATUS", payload: "connecting" });
338
- dispatch({ type: "SET_ERROR", payload: null });
339
-
340
- try {
341
- const session = await client.connectPasskeys();
342
- await storage.save(session);
343
- updateStateFromSession(session);
344
- if (!await runSiwx(session)) return;
345
- dispatch({ type: "SET_STATUS", payload: "connected" });
346
- } catch (error) {
347
- const message = error instanceof Error ? error.message : "Passkeys connection failed";
348
- dispatch({ type: "SET_ERROR", payload: error instanceof Error ? error : new Error(message) });
349
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
350
- }
351
- }, [client, storage, updateStateFromSession, runSiwx]);
352
-
353
- const disconnect = useCallback(async () => {
354
- if (!state.session) {
355
- dispatch({ type: "RESET" });
356
- return;
357
- }
358
-
359
- try {
360
- await client.disconnect(state.session);
361
- } catch (error) {
362
- logger.error("react/provider", "Disconnect error:", error);
363
- }
364
-
365
- // Also disconnect via SessionManager
366
- try {
367
- const sm = sessionManagerRef.current;
368
- if (sm) {
369
- await sm.disconnect();
370
- }
371
- } catch (smError) {
372
- logger.warn("react/provider", "SessionManager disconnect error:", smError);
373
- }
374
-
375
- await storage.clear();
376
- dispatch({ type: "RESET" });
377
- }, [client, state.session, storage]);
378
-
379
- const connectInjected = useCallback(async (walletId?: string): Promise<void> => {
380
- dispatch({ type: "SET_STATUS", payload: "connecting" });
381
- dispatch({ type: "SET_ERROR", payload: null });
382
-
383
- try {
384
- const session = await withTimeout(
385
- client.connectInjected(walletId),
386
- connectionTimeout,
387
- "Injected wallet connect"
388
- );
389
- await storage.save(session);
390
- updateStateFromSession(session);
391
-
392
- // Feed the session into SessionManager
393
- try {
394
- const sm = sessionManagerRef.current;
395
- if (sm) {
396
- const evmChain = session.namespaces["eip155"]?.chains?.[0];
397
- const chainId = evmChain ?? "eip155:1";
398
- sm.connect("eip6963", chainId);
399
- }
400
- } catch (smError) {
401
- logger.warn("react/provider", "SessionManager sync error:", smError);
402
- }
403
-
404
- if (!await runSiwx(session)) return;
405
- dispatch({ type: "SET_STATUS", payload: "connected" });
406
- } catch (error) {
407
- const message = error instanceof Error ? error.message : "Connection failed";
408
- dispatch({ type: "SET_ERROR", payload: error instanceof Error ? error : new Error(message) });
409
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
410
- }
411
- }, [client, storage, updateStateFromSession, connectionTimeout, runSiwx]);
412
-
413
- const startPairing = useCallback(async () => {
414
- return client.startPairing();
415
- }, [client]);
416
-
417
- const completePairing = useCallback(async () => {
418
- const session = await client.completePairing();
419
- await storage.save(session);
420
- updateStateFromSession(session);
421
- if (!await runSiwx(session)) return session;
422
- dispatch({ type: "SET_STATUS", payload: "connected" });
423
- return session;
424
- }, [client, storage, updateStateFromSession, runSiwx]);
425
-
426
- const reconnect = useCallback(async () => {
427
- const savedSession = await storage.load();
428
- if (!savedSession) {
429
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
430
- return;
431
- }
432
-
433
- dispatch({ type: "SET_STATUS", payload: "reconnecting" });
434
-
435
- try {
436
- const session = await withRetry(
437
- () => client.reconnect(savedSession),
438
- { maxRetries, baseDelay: 1000, label: "reconnect" }
439
- );
440
- updateStateFromSession(session);
441
-
442
- // Restore SessionManager from persistence
443
- try {
444
- const sm = sessionManagerRef.current;
445
- if (sm) {
446
- await sm.restoreFromPersistence();
447
- }
448
- } catch (smError) {
449
- logger.warn("react/provider", "SessionManager restore error:", smError);
450
- }
451
-
452
- dispatch({ type: "SET_STATUS", payload: "connected" });
453
- } catch (error) {
454
- logger.error("react/provider", "Reconnect error:", error);
455
- await storage.clear();
456
- dispatch({ type: "SET_STATUS", payload: "disconnected" });
457
- dispatch({ type: "SET_SESSION", payload: null });
458
- }
459
- }, [client, storage, updateStateFromSession, maxRetries]);
460
-
461
- const switchChain = useCallback(async (chainId: string) => {
462
- const sm = sessionManagerRef.current;
463
- if (sm) {
464
- // Use SessionManager's switchChain which handles fee sync + events
465
- await sm.switchChain(chainId);
466
- dispatch({ type: "SET_CHAIN", payload: chainId });
467
- return;
468
- }
469
-
470
- // Fallback to direct connector switching (no SessionManager)
471
- if (!state.session) {
472
- throw new Error("No active session");
473
- }
474
-
475
- try {
476
- if (state.session.walletType === "eip6963" || state.session.id?.startsWith("eip6963-")) {
477
- await eip6963Connector.switchChain(state.session, chainId);
478
- } else if (state.session.walletType === "solana" && client.solanaConnector) {
479
- await client.solanaConnector.switchChain?.(state.session, chainId);
480
- } else {
481
- await client.connector.switchChain(state.session, chainId);
482
- }
483
- dispatch({ type: "SET_CHAIN", payload: chainId });
484
- } catch (error) {
485
- throw new WalletError("chain_unsupported", "Failed to switch chain", error);
486
- }
487
- }, [client, state.session]);
488
-
489
- useEffect(() => {
490
- if (autoConnect) {
491
- reconnect();
492
- }
493
- }, [autoConnect, reconnect]);
494
-
495
- const clearError = useCallback(() => {
496
- dispatch({ type: "SET_ERROR", payload: null });
497
- }, []);
498
-
499
- const value = useMemo<Web3ContextValue>(
500
- () => ({
501
- ...state,
502
- connect,
503
- connectEmbedded,
504
- connectPasskeys,
505
- disconnect,
506
- reconnect,
507
- switchChain,
508
- startPairing,
509
- completePairing,
510
- connectInjected,
511
- clearError,
512
- isConnected: state.status === "connected",
513
- chains,
514
- sessionManager,
515
- }),
516
- [state, connect, connectEmbedded, connectPasskeys,
517
- disconnect, reconnect, switchChain,
518
- startPairing, completePairing, connectInjected, clearError, chains, sessionManager]
519
- );
520
-
521
- return <Web3Context.Provider value={value}>{children}</Web3Context.Provider>;
522
- }
523
-
524
- export function useWeb3(): Web3ContextValue {
525
- const context = useContext(Web3Context);
526
- if (!context) {
527
- throw new Error("useWeb3 must be used within a Web3ConnectProvider");
528
- }
529
- return context;
530
- }