@naculus/connect-appkit-react 0.1.9 → 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.
- package/README.md +4 -4
- package/dist/client.cjs +1 -1
- package/dist/client.cjs.map +1 -1
- package/dist/client.d.cts +144 -0
- package/dist/client.d.ts +144 -0
- package/dist/client.js +1 -1
- package/dist/client.js.map +1 -1
- package/dist/index.cjs +2 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2270 -0
- package/dist/index.d.ts +2270 -0
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/package.json +30 -12
- package/api-extractor.json +0 -21
- package/src/chain-abstraction/index.ts +0 -8
- package/src/chain-abstraction/useCompareCosts.ts +0 -137
- package/src/chain-abstraction/useExecuteRoute.ts +0 -129
- package/src/chain-abstraction/useRouteQuote.ts +0 -168
- package/src/client.test.ts +0 -242
- package/src/client.ts +0 -265
- package/src/hooks/useAccount.test.ts +0 -67
- package/src/hooks/useAccount.ts +0 -37
- package/src/hooks/useBalance.test.ts +0 -459
- package/src/hooks/useBalance.ts +0 -170
- package/src/hooks/useChain.test.ts +0 -160
- package/src/hooks/useChain.ts +0 -53
- package/src/hooks/useConnect.test.ts +0 -112
- package/src/hooks/useConnect.ts +0 -29
- package/src/hooks/useDisconnect.test.ts +0 -75
- package/src/hooks/useDisconnect.ts +0 -32
- package/src/hooks/useERC20Allowance.ts +0 -93
- package/src/hooks/useERC20Approve.ts +0 -220
- package/src/hooks/useERC20Transfer.ts +0 -134
- package/src/hooks/useERC20TransferSimulation.ts +0 -147
- package/src/hooks/useEmbeddedWallet.test.ts +0 -266
- package/src/hooks/useEmbeddedWallet.ts +0 -181
- package/src/hooks/useLastTx.test.ts +0 -117
- package/src/hooks/useLastTx.ts +0 -73
- package/src/hooks/useLookupAddress.ts +0 -131
- package/src/hooks/useNotification.ts +0 -308
- package/src/hooks/useResolveName.ts +0 -128
- package/src/hooks/useSIWxLogin.test.ts +0 -307
- package/src/hooks/useSIWxLogin.ts +0 -163
- package/src/hooks/useSIWxSession.test.ts +0 -481
- package/src/hooks/useSIWxSession.ts +0 -290
- package/src/hooks/useSendCalls.ts +0 -103
- package/src/hooks/useSendTransaction.test.ts +0 -175
- package/src/hooks/useSendTransaction.ts +0 -80
- package/src/hooks/useSendUserOperation.ts +0 -313
- package/src/hooks/useSession.ts +0 -96
- package/src/hooks/useSessionKeys.ts +0 -356
- package/src/hooks/useSignInWithEthereum.test.ts +0 -224
- package/src/hooks/useSignInWithEthereum.ts +0 -46
- package/src/hooks/useSignInWithX.test.ts +0 -210
- package/src/hooks/useSignInWithX.ts +0 -141
- package/src/hooks/useSignMessage.test.ts +0 -151
- package/src/hooks/useSignMessage.ts +0 -65
- package/src/hooks/useSimulateTransfer.ts +0 -165
- package/src/hooks/useSiwxAuthSession.test.ts +0 -456
- package/src/hooks/useSiwxAuthSession.ts +0 -163
- package/src/hooks/useSmartAccount.ts +0 -194
- package/src/hooks/useSwitchChain.ts +0 -68
- package/src/hooks/useTokenBalance.test.ts +0 -337
- package/src/hooks/useTokenBalance.ts +0 -210
- package/src/hooks/useTransactionSimulation.ts +0 -401
- package/src/hooks/useTxHistory.test.ts +0 -108
- package/src/hooks/useTxHistory.ts +0 -83
- package/src/hooks/useTxMonitor.test.ts +0 -127
- package/src/hooks/useTxMonitor.ts +0 -178
- package/src/hooks/useUserOpStatus.ts +0 -245
- package/src/hooks/useValidateDestination.test.ts +0 -96
- package/src/hooks/useValidateDestination.ts +0 -72
- package/src/hooks/useViemClient.test.ts +0 -155
- package/src/hooks/useViemClient.ts +0 -65
- package/src/hooks/useWallet.test.ts +0 -133
- package/src/hooks/useWallet.ts +0 -39
- package/src/hooks/useWeb3ErrorHandler.ts +0 -102
- package/src/index.ts +0 -186
- package/src/provider/Web3ConnectProvider.test.tsx +0 -178
- package/src/provider/Web3ConnectProvider.tsx +0 -530
- package/src/token-list/TokenSelector.tsx +0 -351
- package/src/token-list/defaults.ts +0 -39
- package/src/token-list/index.ts +0 -14
- package/src/token-list/useTokenList.ts +0 -119
- package/src/token-list/useTokenSearch.ts +0 -99
- package/src/types/index.ts +0 -99
- package/src/utils/chains.ts +0 -115
- package/src/utils/errorMessages.ts +0 -142
- package/src/utils/i18n.ts +0 -90
- package/src/wc-generated/components.ts +0 -377
- package/test/setup.ts +0 -17
- package/test/test-utils.tsx +0 -78
- package/tsup.config.ts +0 -18
|
@@ -1,163 +0,0 @@
|
|
|
1
|
-
import { useState, useCallback, useEffect, useRef } from "react";
|
|
2
|
-
import { useSignInWithX } from "./useSignInWithX";
|
|
3
|
-
import type { UseSignInWithXOptions } from "./useSignInWithX";
|
|
4
|
-
import { LocalStorageAdapter, logger } from "@naculus/connect-core";
|
|
5
|
-
import type { SiwxResult } from "@naculus/siwx";
|
|
6
|
-
|
|
7
|
-
// ── Types ────────────────────────────────────────────────────────
|
|
8
|
-
|
|
9
|
-
export interface UseSiwxAuthSessionOptions {
|
|
10
|
-
/** Storage key prefix (default: "naculus_") */
|
|
11
|
-
storagePrefix?: string;
|
|
12
|
-
/** Auto-restore auth from storage on mount (default: true) */
|
|
13
|
-
autoRestore?: boolean;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export interface UseSiwxAuthSessionReturn {
|
|
17
|
-
/** Whether a valid SIWx auth session exists */
|
|
18
|
-
isSignedIn: boolean;
|
|
19
|
-
/** Whether we're still checking persisted auth on mount */
|
|
20
|
-
isRestoring: boolean;
|
|
21
|
-
/** The persisted SIWx result, or null if not signed in */
|
|
22
|
-
siwxResult: SiwxResult | null;
|
|
23
|
-
/** Whether a sign-in is in progress */
|
|
24
|
-
isSigningIn: boolean;
|
|
25
|
-
/** Last sign-in error */
|
|
26
|
-
error: Error | null;
|
|
27
|
-
/** Sign in with optional overrides. Persists result to storage on success. */
|
|
28
|
-
signIn: (options?: UseSignInWithXOptions) => Promise<SiwxResult>;
|
|
29
|
-
/** Sign out: clears persisted auth and resets state */
|
|
30
|
-
signOut: () => void;
|
|
31
|
-
/** Clear the last error */
|
|
32
|
-
clearError: () => void;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
// ── Constants ────────────────────────────────────────────────────
|
|
36
|
-
|
|
37
|
-
const SIWX_AUTH_KEY = "siwx_auth";
|
|
38
|
-
|
|
39
|
-
// ── Helpers ──────────────────────────────────────────────────────
|
|
40
|
-
|
|
41
|
-
function getStorage(prefix: string): LocalStorageAdapter {
|
|
42
|
-
return new LocalStorageAdapter(prefix);
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
function isExpired(siwxResult: SiwxResult, now: Date): boolean {
|
|
46
|
-
if (!siwxResult.message.expirationTime) return false;
|
|
47
|
-
return new Date(siwxResult.message.expirationTime).getTime() <= now.getTime();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function isNotBeforeValid(siwxResult: SiwxResult, now: Date): boolean {
|
|
51
|
-
if (!siwxResult.message.notBefore) return true;
|
|
52
|
-
return new Date(siwxResult.message.notBefore).getTime() <= now.getTime();
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// ── Hook ─────────────────────────────────────────────────────────
|
|
56
|
-
|
|
57
|
-
export function useSiwxAuthSession(
|
|
58
|
-
options?: UseSiwxAuthSessionOptions
|
|
59
|
-
): UseSiwxAuthSessionReturn {
|
|
60
|
-
const { storagePrefix = "naculus_", autoRestore = true } = options ?? {};
|
|
61
|
-
|
|
62
|
-
const [siwxResult, setSiwxResult] = useState<SiwxResult | null>(null);
|
|
63
|
-
const [isRestoring, setIsRestoring] = useState(autoRestore);
|
|
64
|
-
const [isSigningIn, setIsSigningIn] = useState(false);
|
|
65
|
-
const [error, setError] = useState<Error | null>(null);
|
|
66
|
-
|
|
67
|
-
// Use the generic SIWx hook for the underlying signing flow.
|
|
68
|
-
const signInWithX = useSignInWithX();
|
|
69
|
-
const storageRef = useRef(getStorage(storagePrefix));
|
|
70
|
-
|
|
71
|
-
const clearError = useCallback(() => setError(null), []);
|
|
72
|
-
|
|
73
|
-
// ── Restore persisted auth on mount ────────────────────────────
|
|
74
|
-
|
|
75
|
-
useEffect(() => {
|
|
76
|
-
if (!autoRestore) {
|
|
77
|
-
setIsRestoring(false);
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
let cancelled = false;
|
|
82
|
-
|
|
83
|
-
(async () => {
|
|
84
|
-
try {
|
|
85
|
-
const storage = storageRef.current;
|
|
86
|
-
const saved = await storage.get<SiwxResult>(SIWX_AUTH_KEY);
|
|
87
|
-
|
|
88
|
-
if (cancelled) return;
|
|
89
|
-
|
|
90
|
-
if (saved && !isExpired(saved, new Date()) && isNotBeforeValid(saved, new Date())) {
|
|
91
|
-
logger.info("react/useSiwxAuthSession", "Restored persisted SIWx auth session");
|
|
92
|
-
setSiwxResult(saved);
|
|
93
|
-
setError(null);
|
|
94
|
-
} else if (saved) {
|
|
95
|
-
// Expired or not-yet-valid — clean up stale entry
|
|
96
|
-
logger.info("react/useSiwxAuthSession", "Persisted SIWx auth expired, clearing");
|
|
97
|
-
await storage.remove(SIWX_AUTH_KEY);
|
|
98
|
-
}
|
|
99
|
-
} catch (err) {
|
|
100
|
-
logger.warn("react/useSiwxAuthSession", "Failed to restore SIWx auth:", err);
|
|
101
|
-
} finally {
|
|
102
|
-
if (!cancelled) setIsRestoring(false);
|
|
103
|
-
}
|
|
104
|
-
})();
|
|
105
|
-
|
|
106
|
-
return () => {
|
|
107
|
-
cancelled = true;
|
|
108
|
-
};
|
|
109
|
-
}, [autoRestore]);
|
|
110
|
-
|
|
111
|
-
// ── Sign In ────────────────────────────────────────────────────
|
|
112
|
-
|
|
113
|
-
const signIn = useCallback(
|
|
114
|
-
async (signOptions?: UseSignInWithXOptions): Promise<SiwxResult> => {
|
|
115
|
-
setIsSigningIn(true);
|
|
116
|
-
setError(null);
|
|
117
|
-
|
|
118
|
-
try {
|
|
119
|
-
const result = await signInWithX.signIn(signOptions);
|
|
120
|
-
|
|
121
|
-
// Persist to storage
|
|
122
|
-
const storage = storageRef.current;
|
|
123
|
-
await storage.set(SIWX_AUTH_KEY, result);
|
|
124
|
-
|
|
125
|
-
setSiwxResult(result);
|
|
126
|
-
setIsSigningIn(false);
|
|
127
|
-
return result;
|
|
128
|
-
} catch (err) {
|
|
129
|
-
const wrapped = err instanceof Error ? err : new Error("SIWx sign-in failed");
|
|
130
|
-
setError(wrapped);
|
|
131
|
-
setIsSigningIn(false);
|
|
132
|
-
throw wrapped;
|
|
133
|
-
}
|
|
134
|
-
},
|
|
135
|
-
[signInWithX]
|
|
136
|
-
);
|
|
137
|
-
|
|
138
|
-
// ── Sign Out ───────────────────────────────────────────────────
|
|
139
|
-
|
|
140
|
-
const signOut = useCallback(async () => {
|
|
141
|
-
try {
|
|
142
|
-
const storage = storageRef.current;
|
|
143
|
-
await storage.remove(SIWX_AUTH_KEY);
|
|
144
|
-
} catch (err) {
|
|
145
|
-
logger.warn("react/useSiwxAuthSession", "Failed to clear SIWx auth:", err);
|
|
146
|
-
}
|
|
147
|
-
setSiwxResult(null);
|
|
148
|
-
setError(null);
|
|
149
|
-
}, []);
|
|
150
|
-
|
|
151
|
-
// ── Result ─────────────────────────────────────────────────────
|
|
152
|
-
|
|
153
|
-
return {
|
|
154
|
-
isSignedIn: siwxResult !== null,
|
|
155
|
-
isRestoring,
|
|
156
|
-
siwxResult,
|
|
157
|
-
isSigningIn,
|
|
158
|
-
error,
|
|
159
|
-
signIn,
|
|
160
|
-
signOut,
|
|
161
|
-
clearError,
|
|
162
|
-
};
|
|
163
|
-
}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useSmartAccount
|
|
3
|
-
*
|
|
4
|
-
* React hook for ERC-4337 Smart Account lifecycle management.
|
|
5
|
-
* Provides create, deploy, and address lookup for smart contract wallets.
|
|
6
|
-
*
|
|
7
|
-
* @example
|
|
8
|
-
* ```tsx
|
|
9
|
-
* const { address, isDeployed, createWallet, deployWallet, isLoading } = useSmartAccount({
|
|
10
|
-
* rpcUrl: "https://eth.llamarpc.com",
|
|
11
|
-
* bundlerUrl: "https://api.pimlico.io/v2/1/rpc?apikey=...",
|
|
12
|
-
* });
|
|
13
|
-
* ```
|
|
14
|
-
*/
|
|
15
|
-
|
|
16
|
-
import { useState, useCallback, useEffect, useRef } from "react";
|
|
17
|
-
import { useAccount } from "./useAccount";
|
|
18
|
-
import type {
|
|
19
|
-
SmartAccountInfo,
|
|
20
|
-
SmartAccountConfig,
|
|
21
|
-
Address,
|
|
22
|
-
} from "@naculus/connect-core";
|
|
23
|
-
|
|
24
|
-
export interface UseSmartAccountOptions {
|
|
25
|
-
/** RPC URL for the target chain */
|
|
26
|
-
rpcUrl?: string;
|
|
27
|
-
/** Bundler RPC URL */
|
|
28
|
-
bundlerUrl?: string;
|
|
29
|
-
/** Chain ID (CAIP-2 format) */
|
|
30
|
-
chainId?: string;
|
|
31
|
-
/** Account type (default: "simple") */
|
|
32
|
-
accountType?: "simple" | "light" | "kernel" | "safe";
|
|
33
|
-
/** Optional salt for deterministic address */
|
|
34
|
-
salt?: bigint;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export interface UseSmartAccountReturn {
|
|
38
|
-
/** Smart account address (null if not created) */
|
|
39
|
-
address: Address | null;
|
|
40
|
-
/** Whether the account is deployed on-chain */
|
|
41
|
-
isDeployed: boolean;
|
|
42
|
-
/** Smart account info object */
|
|
43
|
-
accountInfo: SmartAccountInfo | null;
|
|
44
|
-
/** Loading state */
|
|
45
|
-
isLoading: boolean;
|
|
46
|
-
/** Error state */
|
|
47
|
-
error: Error | null;
|
|
48
|
-
/** Create a new smart account (compute address) */
|
|
49
|
-
createWallet: () => Promise<SmartAccountInfo | null>;
|
|
50
|
-
/** Deploy the smart account to chain */
|
|
51
|
-
deployWallet: () => Promise<Address | null>;
|
|
52
|
-
/** Get the counterfactual address without creating */
|
|
53
|
-
getAddress: () => Promise<Address | null>;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
/**
|
|
57
|
-
* Hook for managing a ERC-4337 Smart Contract Wallet lifecycle.
|
|
58
|
-
*
|
|
59
|
-
* @param options - Smart account configuration options
|
|
60
|
-
* @returns Smart account state and actions
|
|
61
|
-
*/
|
|
62
|
-
export function useSmartAccount(options?: UseSmartAccountOptions): UseSmartAccountReturn {
|
|
63
|
-
const { evmAccount } = useAccount();
|
|
64
|
-
const [address, setAddress] = useState<Address | null>(null);
|
|
65
|
-
const [isDeployed, setIsDeployed] = useState(false);
|
|
66
|
-
const [accountInfo, setAccountInfo] = useState<SmartAccountInfo | null>(null);
|
|
67
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
68
|
-
const [error, setError] = useState<Error | null>(null);
|
|
69
|
-
const managerRef = useRef<import("@naculus/connect-core").SmartAccountManager | null>(null);
|
|
70
|
-
|
|
71
|
-
// Initialize SmartAccountManager on config change (with cleanup to prevent race conditions)
|
|
72
|
-
useEffect(() => {
|
|
73
|
-
if (!options?.rpcUrl) {
|
|
74
|
-
managerRef.current = null;
|
|
75
|
-
return;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
let cancelled = false;
|
|
79
|
-
|
|
80
|
-
import("@naculus/connect-core").then(({ SmartAccountManager }) => {
|
|
81
|
-
if (cancelled) return; // prevent stale state update
|
|
82
|
-
managerRef.current = new SmartAccountManager({
|
|
83
|
-
rpcUrl: options.rpcUrl!,
|
|
84
|
-
chainId: options.chainId ?? "eip155:1",
|
|
85
|
-
bundlerClient: {
|
|
86
|
-
url: options.bundlerUrl ?? "",
|
|
87
|
-
},
|
|
88
|
-
});
|
|
89
|
-
}).catch((err) => {
|
|
90
|
-
if (cancelled) return; // prevent stale state update
|
|
91
|
-
setError(err instanceof Error ? err : new Error("Failed to load account-abstraction module"));
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
return () => { cancelled = true; };
|
|
95
|
-
}, [options?.rpcUrl, options?.bundlerUrl, options?.chainId]);
|
|
96
|
-
|
|
97
|
-
// Get account config from options + connected EOA
|
|
98
|
-
const getConfig = useCallback((): SmartAccountConfig | null => {
|
|
99
|
-
const owner = evmAccount;
|
|
100
|
-
if (!owner || !managerRef.current) return null;
|
|
101
|
-
|
|
102
|
-
const address = owner.includes(":") ? owner.split(":").pop()! as Address : owner as Address;
|
|
103
|
-
|
|
104
|
-
return {
|
|
105
|
-
owner: address,
|
|
106
|
-
accountType: options?.accountType ?? "simple",
|
|
107
|
-
entryPoint: "0x0000000071727De22E5E9d8BAf0edAc6f37da032" as Address, // v0.7
|
|
108
|
-
chainId: options?.chainId ?? "eip155:1",
|
|
109
|
-
salt: options?.salt,
|
|
110
|
-
};
|
|
111
|
-
}, [evmAccount, options?.accountType, options?.chainId, options?.salt]);
|
|
112
|
-
|
|
113
|
-
// Create wallet (compute counterfactual address)
|
|
114
|
-
const createWallet = useCallback(async (): Promise<SmartAccountInfo | null> => {
|
|
115
|
-
const config = getConfig();
|
|
116
|
-
if (!config || !managerRef.current) {
|
|
117
|
-
setError(new Error("Smart account not configured"));
|
|
118
|
-
return null;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
setIsLoading(true);
|
|
122
|
-
setError(null);
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
const info = await managerRef.current.createAccount(config);
|
|
126
|
-
setAddress(info.address);
|
|
127
|
-
setIsDeployed(info.isDeployed);
|
|
128
|
-
setAccountInfo(info);
|
|
129
|
-
return info;
|
|
130
|
-
} catch (err) {
|
|
131
|
-
const e = err instanceof Error ? err : new Error("Failed to create smart account");
|
|
132
|
-
setError(e);
|
|
133
|
-
return null;
|
|
134
|
-
} finally {
|
|
135
|
-
setIsLoading(false);
|
|
136
|
-
}
|
|
137
|
-
}, [getConfig]);
|
|
138
|
-
|
|
139
|
-
// Deploy wallet
|
|
140
|
-
const deployWallet = useCallback(async (): Promise<Address | null> => {
|
|
141
|
-
const config = getConfig();
|
|
142
|
-
if (!config || !managerRef.current) {
|
|
143
|
-
setError(new Error("Smart account not configured"));
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
setIsLoading(true);
|
|
148
|
-
setError(null);
|
|
149
|
-
|
|
150
|
-
try {
|
|
151
|
-
const deployResult = await managerRef.current.deployAccount(config);
|
|
152
|
-
|
|
153
|
-
// After deploy, update state
|
|
154
|
-
if (deployResult) {
|
|
155
|
-
const info = await managerRef.current.createAccount(config);
|
|
156
|
-
setAddress(info.address);
|
|
157
|
-
setIsDeployed(true);
|
|
158
|
-
setAccountInfo(info);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
return deployResult;
|
|
162
|
-
} catch (err) {
|
|
163
|
-
const e = err instanceof Error ? err : new Error("Failed to deploy smart account");
|
|
164
|
-
setError(e);
|
|
165
|
-
return null;
|
|
166
|
-
} finally {
|
|
167
|
-
setIsLoading(false);
|
|
168
|
-
}
|
|
169
|
-
}, [getConfig]);
|
|
170
|
-
|
|
171
|
-
// Get counterfactual address
|
|
172
|
-
const getAddress = useCallback(async (): Promise<Address | null> => {
|
|
173
|
-
const config = getConfig();
|
|
174
|
-
if (!config || !managerRef.current) return null;
|
|
175
|
-
|
|
176
|
-
try {
|
|
177
|
-
const addr = await managerRef.current.getAccountAddress(config);
|
|
178
|
-
return addr;
|
|
179
|
-
} catch {
|
|
180
|
-
return null;
|
|
181
|
-
}
|
|
182
|
-
}, [getConfig]);
|
|
183
|
-
|
|
184
|
-
return {
|
|
185
|
-
address,
|
|
186
|
-
isDeployed,
|
|
187
|
-
accountInfo,
|
|
188
|
-
isLoading,
|
|
189
|
-
error,
|
|
190
|
-
createWallet,
|
|
191
|
-
deployWallet,
|
|
192
|
-
getAddress,
|
|
193
|
-
};
|
|
194
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* useSwitchChain Hook
|
|
3
|
-
*
|
|
4
|
-
* Provides the switchChain method with loading/error state tracking.
|
|
5
|
-
*
|
|
6
|
-
* @see SRS-009 §7.2
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
import { useState, useCallback } from "react";
|
|
10
|
-
import { useWeb3 } from "../provider/Web3ConnectProvider";
|
|
11
|
-
import { WalletError } from "@naculus/connect-core";
|
|
12
|
-
|
|
13
|
-
export interface UseSwitchChainReturn {
|
|
14
|
-
/** Switch the active chain for the current session */
|
|
15
|
-
switchChain: (chainId: string) => Promise<void>;
|
|
16
|
-
/** Whether a chain switch is in progress */
|
|
17
|
-
isSwitching: boolean;
|
|
18
|
-
/** The currently active chain ID */
|
|
19
|
-
currentChainId: string | null;
|
|
20
|
-
/** The last error that occurred during chain switch (if any) */
|
|
21
|
-
error: Error | null;
|
|
22
|
-
/** Clear the error state */
|
|
23
|
-
clearError: () => void;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function useSwitchChain(): UseSwitchChainReturn {
|
|
27
|
-
const { switchChain: providerSwitchChain, chainId } = useWeb3();
|
|
28
|
-
const [isSwitching, setIsSwitching] = useState(false);
|
|
29
|
-
const [error, setError] = useState<Error | null>(null);
|
|
30
|
-
|
|
31
|
-
const handleSwitchChain = useCallback(
|
|
32
|
-
async (targetChainId: string) => {
|
|
33
|
-
setIsSwitching(true);
|
|
34
|
-
setError(null);
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
await providerSwitchChain(targetChainId);
|
|
38
|
-
} catch (err) {
|
|
39
|
-
const walletError =
|
|
40
|
-
err instanceof WalletError
|
|
41
|
-
? err
|
|
42
|
-
: new WalletError(
|
|
43
|
-
"chain_unsupported",
|
|
44
|
-
err instanceof Error
|
|
45
|
-
? err.message
|
|
46
|
-
: "Unknown error during chain switch",
|
|
47
|
-
);
|
|
48
|
-
setError(walletError);
|
|
49
|
-
throw walletError;
|
|
50
|
-
} finally {
|
|
51
|
-
setIsSwitching(false);
|
|
52
|
-
}
|
|
53
|
-
},
|
|
54
|
-
[providerSwitchChain],
|
|
55
|
-
);
|
|
56
|
-
|
|
57
|
-
const clearError = useCallback(() => {
|
|
58
|
-
setError(null);
|
|
59
|
-
}, []);
|
|
60
|
-
|
|
61
|
-
return {
|
|
62
|
-
switchChain: handleSwitchChain,
|
|
63
|
-
isSwitching,
|
|
64
|
-
currentChainId: chainId,
|
|
65
|
-
error,
|
|
66
|
-
clearError,
|
|
67
|
-
};
|
|
68
|
-
}
|