UNPKG

@stablecoin.xyz/react

Version:

React hooks and components for SBC Account Abstraction

831 lines (819 loc) 31.1 kB
'use strict'; var react = require('react'); var jsxRuntime = require('react/jsx-runtime'); var core = require('@stablecoin.xyz/core'); const SbcContext = react.createContext(void 0); function SbcProvider({ config, children, onError }) { const [sbcAppKit, setSbcAppKit] = react.useState(null); const [isInitialized, setIsInitialized] = react.useState(false); const [error, setError] = react.useState(null); const initialize = react.useCallback(async () => { try { setError(null); setIsInitialized(false); const appKit = new core.SbcAppKit(config); setSbcAppKit(appKit); setIsInitialized(true); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC App Kit"); if (config.debug) { console.error("[SBC App Kit] Initialization failed:", error2); console.error("[SBC App Kit] Config:", { chain: config.chain?.name, chainId: config.chain?.id, wallet: config.wallet, hasApiKey: !!config.apiKey, apiKeyValid: config.apiKey?.startsWith("sbc-") }); } setError(error2); setSbcAppKit(null); setIsInitialized(false); onError?.(error2); } }, [config, onError]); react.useEffect(() => { initialize(); }, [initialize]); react.useEffect(() => { return () => { }; }, [sbcAppKit]); const contextValue = { sbcAppKit, isInitialized, error }; return /* @__PURE__ */ jsxRuntime.jsx(SbcContext.Provider, { value: contextValue, children }); } function useSbcContext() { const context = react.useContext(SbcContext); if (context === void 0) { throw new Error("useSbcContext must be used within a SbcProvider"); } return context; } function useSbcApp() { const { sbcAppKit, isInitialized, error } = useSbcContext(); const [account, setAccount] = react.useState(null); const [isLoadingAccount, setIsLoadingAccount] = react.useState(false); const [accountError, setAccountError] = react.useState(null); const [ownerAddress, setOwnerAddress] = react.useState(null); const refreshAccount = react.useCallback(async () => { if (!sbcAppKit || !isInitialized) { setAccount(null); setOwnerAddress(null); return; } try { setIsLoadingAccount(true); setAccountError(null); try { const owner = sbcAppKit.getOwnerAddress(); setOwnerAddress(owner); const accountInfo = await sbcAppKit.getAccount(); setAccount(accountInfo); } catch (ownerError) { setOwnerAddress(null); setAccount(null); return; } } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to load account"); if (sbcAppKit && sbcAppKit.debug) { console.error("[SBC App Kit] Failed to load account:", error2); } setAccountError(error2); setAccount(null); setOwnerAddress(null); } finally { setIsLoadingAccount(false); } }, [sbcAppKit, isInitialized]); const disconnectWallet = react.useCallback(() => { if (sbcAppKit) { try { sbcAppKit.disconnectWallet(); } catch { } } setAccount(null); setOwnerAddress(null); }, [sbcAppKit]); react.useEffect(() => { if (isInitialized && sbcAppKit) { refreshAccount(); } else { setAccount(null); setAccountError(null); setOwnerAddress(null); } }, [isInitialized, sbcAppKit, refreshAccount]); return { sbcAppKit, isInitialized, error, account, isLoadingAccount, accountError, refreshAccount, ownerAddress, disconnectWallet }; } function useUserOperation(options = {}) { const { sbcAppKit, isInitialized } = useSbcContext(); const { refreshAccount } = useSbcApp(); const { onSuccess, onError, refreshAccount: shouldRefreshAccount = true } = options; const [isLoading, setIsLoading] = react.useState(false); const [isSuccess, setIsSuccess] = react.useState(false); const [isError, setIsError] = react.useState(false); const [error, setError] = react.useState(null); const [data, setData] = react.useState(null); const reset = react.useCallback(() => { setIsLoading(false); setIsSuccess(false); setIsError(false); setError(null); setData(null); }, []); const sendUserOperation = react.useCallback(async (params) => { if (!sbcAppKit || !isInitialized) { const error2 = new Error("SBC App Kit is not initialized"); if (sbcAppKit && sbcAppKit.debug) { console.error("[SBC App Kit] Cannot send user operation: SDK not initialized"); } setError(error2); setIsError(true); onError?.(error2); return; } try { setIsLoading(true); setIsError(false); setError(null); setIsSuccess(false); const result = await sbcAppKit.sendUserOperation(params); setData(result); setIsSuccess(true); onSuccess?.(result); if (shouldRefreshAccount) { refreshAccount(); } return result; } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to send user operation"); if (sbcAppKit.debug) { console.error("[SBC App Kit] User operation failed:", error2); console.error("[SBC App Kit] Params:", params); } setError(error2); setIsError(true); setData(null); onError?.(error2); return; } finally { setIsLoading(false); } }, [sbcAppKit, isInitialized, onSuccess, onError, shouldRefreshAccount, refreshAccount]); const estimateUserOperation = react.useCallback(async (params) => { if (!sbcAppKit || !isInitialized) { const error2 = new Error("SBC App Kit is not initialized"); if (sbcAppKit && sbcAppKit.debug) { console.error("[SBC App Kit] Cannot estimate user operation: SDK not initialized"); } setError(error2); setIsError(true); onError?.(error2); return; } try { return await sbcAppKit.estimateUserOperation(params); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to estimate user operation"); if (sbcAppKit.debug) { console.error("[SBC App Kit] Gas estimation failed:", error2); console.error("[SBC App Kit] Params:", params); } setError(error2); setIsError(true); onError?.(error2); return; } }, [sbcAppKit, isInitialized, onError]); return { sendUserOperation, estimateUserOperation, isLoading, isSuccess, isError, error, data, reset }; } function useSbcDynamic(config) { const [sbcAppKit, setSbcAppKit] = react.useState(null); const [isInitialized, setIsInitialized] = react.useState(false); const [error, setError] = react.useState(null); const [account, setAccount] = react.useState(null); const [isLoadingAccount, setIsLoadingAccount] = react.useState(false); const [accountError, setAccountError] = react.useState(null); const [ownerAddress, setOwnerAddress] = react.useState(null); react.useEffect(() => { const initializeSbc = async () => { if (!config.primaryWallet?.address) { setSbcAppKit(null); setIsInitialized(false); setError(null); return; } try { setError(null); let dynamicWalletClient = null; try { dynamicWalletClient = await config.primaryWallet.connector.getWalletClient(); if (config.debug) { console.log(`[useSbcDynamic] Dynamic wallet client obtained:`, { hasClient: !!dynamicWalletClient, walletAddress: config.primaryWallet.address }); } } catch (e) { throw new Error(`Failed to get Dynamic wallet client: ${e instanceof Error ? e.message : "Unknown error"}`); } if (!dynamicWalletClient) { throw new Error("Dynamic wallet client not available"); } const sbcConfig = { apiKey: config.apiKey, chain: config.chain, wallet: "dynamic", walletOptions: { dynamicContext: { primaryWallet: config.primaryWallet } }, rpcUrl: config.rpcUrl, debug: config.debug }; const appKit = new core.SbcAppKit(sbcConfig); await appKit.connectWallet("dynamic"); setSbcAppKit(appKit); setIsInitialized(true); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC with Dynamic"); setError(error2); setSbcAppKit(null); setIsInitialized(false); } }; initializeSbc(); }, [config.primaryWallet?.address, config.apiKey, config.chain, config.rpcUrl, config.debug]); const refreshAccount = react.useCallback(async () => { if (!sbcAppKit || !isInitialized) { setAccount(null); setOwnerAddress(null); return; } try { setIsLoadingAccount(true); setAccountError(null); const owner = sbcAppKit.getOwnerAddress(); setOwnerAddress(owner); const accountInfo = await sbcAppKit.getAccount(); setAccount(accountInfo); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to load account"); setAccountError(error2); setAccount(null); setOwnerAddress(null); } finally { setIsLoadingAccount(false); } }, [sbcAppKit, isInitialized]); const disconnectWallet = react.useCallback(() => { if (sbcAppKit) { try { sbcAppKit.disconnectWallet(); } catch { } } setAccount(null); setOwnerAddress(null); }, [sbcAppKit]); react.useEffect(() => { if (isInitialized && sbcAppKit) { refreshAccount(); } else { setAccount(null); setAccountError(null); setOwnerAddress(null); } }, [isInitialized, sbcAppKit, refreshAccount]); return { sbcAppKit, isInitialized, error, account, isLoadingAccount, accountError, refreshAccount, ownerAddress, disconnectWallet }; } function useSbcPara(config) { const [sbcAppKit, setSbcAppKit] = react.useState(null); const [isInitialized, setIsInitialized] = react.useState(false); const [error, setError] = react.useState(null); const [account, setAccount] = react.useState(null); const [isLoadingAccount, setIsLoadingAccount] = react.useState(false); const [accountError, setAccountError] = react.useState(null); const [ownerAddress, setOwnerAddress] = react.useState(null); const isLoadingRef = react.useRef(false); const { apiKey, chain, paraAccount, rpcUrl, debug = false, paraViemClients } = config; const hasExternalWallet = paraAccount.isConnected && paraAccount.external?.evm?.address; const hasEmbeddedWallet = paraAccount.isConnected && paraAccount.embedded?.wallets && paraAccount.embedded.wallets.length > 0; react.useEffect(() => { if (!paraAccount.isConnected || !hasExternalWallet && !hasEmbeddedWallet) { setSbcAppKit(null); setIsInitialized(false); setOwnerAddress(null); return; } const initializeSbc = async () => { try { setError(null); if (debug) console.log("Initializing SBC with Para wallet..."); const paraWalletAddress = hasExternalWallet ? paraAccount.external?.evm?.address : hasEmbeddedWallet ? paraAccount.embedded.wallets?.[0]?.address : null; if (!paraWalletAddress) { throw new Error("No Para wallet address found"); } if (!paraViemClients?.walletClient || !paraViemClients?.account) { if (debug) console.log("[useSbcPara] Waiting for Para viem wallet client to be ready..."); return; } const appKit = new core.SbcAppKit({ apiKey, chain, walletClient: paraViemClients.walletClient, rpcUrl, debug }); setSbcAppKit(appKit); setOwnerAddress(paraWalletAddress); setIsInitialized(true); if (debug) console.log("SBC initialized and connected with Para wallet"); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Unknown error during SBC initialization"; if (debug) console.error("SBC initialization failed:", errorMessage); setError(new Error(`SBC initialization failed: ${errorMessage}`)); setSbcAppKit(null); setIsInitialized(false); } }; initializeSbc(); }, [apiKey, chain, rpcUrl, debug, paraAccount.isConnected, hasExternalWallet, hasEmbeddedWallet, paraViemClients?.walletClient, paraViemClients?.account]); react.useEffect(() => { if (!sbcAppKit || !isInitialized || isLoadingRef.current) { return; } const loadAccount = async () => { if (isLoadingRef.current) return; isLoadingRef.current = true; setIsLoadingAccount(true); setAccountError(null); try { if (debug) console.log("Loading Para smart account..."); const accountInfo = await sbcAppKit.getAccount(); setAccount(accountInfo); if (debug) console.log("Para smart account loaded:", accountInfo); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Unknown error loading account"; if (debug) console.error("Failed to load Para smart account:", errorMessage); setAccountError(new Error(`Failed to load account: ${errorMessage}`)); } finally { setIsLoadingAccount(false); isLoadingRef.current = false; } }; loadAccount(); }, [sbcAppKit, isInitialized, debug]); const refreshAccount = react.useCallback(async () => { if (!sbcAppKit || isLoadingRef.current) return; isLoadingRef.current = true; setIsLoadingAccount(true); setAccountError(null); try { if (debug) console.log("Refreshing Para smart account..."); const accountInfo = await sbcAppKit.getAccount(); setAccount(accountInfo); if (debug) console.log("Para smart account refreshed:", accountInfo); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Unknown error refreshing account"; if (debug) console.error("Failed to refresh Para smart account:", errorMessage); setAccountError(new Error(`Failed to refresh account: ${errorMessage}`)); } finally { setIsLoadingAccount(false); isLoadingRef.current = false; } }, [sbcAppKit, debug]); const disconnectWallet = react.useCallback(async () => { try { if (debug) console.log("Cleaning up SBC integration..."); setSbcAppKit(null); setIsInitialized(false); setAccount(null); setOwnerAddress(null); setError(null); setAccountError(null); if (debug) console.log("SBC cleanup successful"); } catch (err) { const errorMessage = err instanceof Error ? err.message : "Unknown error during cleanup"; if (debug) console.error("Failed to cleanup SBC:", errorMessage); setError(new Error(`Failed to cleanup: ${errorMessage}`)); } }, [debug]); return { sbcAppKit, isInitialized, error, account, isLoadingAccount, accountError, ownerAddress, refreshAccount, disconnectWallet }; } function useSbcTurnkey(config) { const [sbcAppKit, setSbcAppKit] = react.useState(null); const [isInitialized, setIsInitialized] = react.useState(false); const [error, setError] = react.useState(null); const [account, setAccount] = react.useState(null); const [isLoadingAccount, setIsLoadingAccount] = react.useState(false); const [accountError, setAccountError] = react.useState(null); const [ownerAddress, setOwnerAddress] = react.useState(null); react.useEffect(() => { const initializeSbc = async () => { const hasWalletClient = !!config.turnkeyWalletClient?.account?.address; const hasTurnkeyClient = !!config.turnkeyClient; if (!config.organizationId || !hasTurnkeyClient && !hasWalletClient) { setSbcAppKit(null); setIsInitialized(false); setError(null); return; } try { setError(null); if (config.debug) { console.log("[useSbcTurnkey] Initializing SBC with Turnkey...", { hasClient: !!config.turnkeyClient, organizationId: config.organizationId, hasWalletClient: !!config.turnkeyWalletClient }); } let walletAddress = null; if (config.debug) { console.log("[useSbcTurnkey] Checking for wallet address:", { hasTurnkeyWalletClient: !!config.turnkeyWalletClient, hasAccount: !!config.turnkeyWalletClient?.account, hasAddress: !!config.turnkeyWalletClient?.account?.address, address: config.turnkeyWalletClient?.account?.address }); } if (config.turnkeyWalletClient?.account?.address) { walletAddress = config.turnkeyWalletClient.account.address; if (config.debug) { console.log("[useSbcTurnkey] Using address from wallet client:", walletAddress); } } else if (config.turnkeyClient) { if (config.debug) { console.log("[useSbcTurnkey] No wallet client address found, fetching from Turnkey..."); } try { const wallets = await config.turnkeyClient.getWallets({ organizationId: config.organizationId }); const walletId = wallets?.wallets[0]?.walletId; if (walletId) { const accounts = await config.turnkeyClient.getWalletAccounts({ organizationId: config.organizationId, walletId }); walletAddress = accounts?.accounts[0]?.address; } } catch (e) { throw new Error(`Failed to fetch Turnkey wallet info: ${e instanceof Error ? e.message : "Unknown error"}`); } } if (!walletAddress) { throw new Error("No Turnkey wallet address found. Create a wallet first or provide turnkeyWalletClient."); } const sbcConfig = { apiKey: config.apiKey, chain: config.chain, wallet: "turnkey", walletOptions: { turnkeyContext: { turnkeyClient: config.turnkeyClient, organizationId: config.organizationId, turnkeyWalletClient: config.turnkeyWalletClient } }, rpcUrl: config.rpcUrl, debug: config.debug }; const appKit = new core.SbcAppKit(sbcConfig); await appKit.connectWallet("turnkey"); setSbcAppKit(appKit); setOwnerAddress(walletAddress); setIsInitialized(true); if (config.debug) { console.log("[useSbcTurnkey] SBC initialized successfully"); } } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to initialize SBC with Turnkey"); setError(error2); setSbcAppKit(null); setIsInitialized(false); if (config.debug) { console.error("[useSbcTurnkey] Initialization failed:", error2); } } }; initializeSbc(); }, [config.turnkeyClient, config.organizationId, config.apiKey, config.chain, config.rpcUrl, config.debug, config.turnkeyWalletClient]); const refreshAccount = react.useCallback(async () => { if (!sbcAppKit || !isInitialized) { setAccount(null); setOwnerAddress(null); return; } try { setIsLoadingAccount(true); setAccountError(null); const owner = sbcAppKit.getOwnerAddress(); setOwnerAddress(owner); const accountInfo = await sbcAppKit.getAccount(); setAccount(accountInfo); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to load account"); setAccountError(error2); setAccount(null); setOwnerAddress(null); } finally { setIsLoadingAccount(false); } }, [sbcAppKit, isInitialized]); const disconnectWallet = react.useCallback(() => { if (sbcAppKit) { try { sbcAppKit.disconnectWallet(); } catch { } } setAccount(null); setOwnerAddress(null); }, [sbcAppKit]); react.useEffect(() => { if (isInitialized && sbcAppKit) { refreshAccount(); } else { setAccount(null); setAccountError(null); setOwnerAddress(null); } }, [isInitialized, sbcAppKit, refreshAccount]); return { sbcAppKit, isInitialized, error, account, isLoadingAccount, accountError, refreshAccount, ownerAddress, disconnectWallet }; } function WalletConnect({ className, onConnectionChange }) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { padding: "12px 16px", border: "1px solid #e0e0e0", borderRadius: "8px", textAlign: "center", backgroundColor: "#f8f9fa" }, children: [ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: "0 0 8px 0", fontSize: "14px", color: "#666" }, children: "\u{1F6A7} Wallet Connection Coming Soon" }), /* @__PURE__ */ jsxRuntime.jsx("p", { style: { margin: 0, fontSize: "12px", color: "#999" }, children: "This component will support multiple wallet providers and connection management." }) ] }) }); } function WalletButton({ walletType = "auto", className = "", onConnect, onError, children, showLoading = true, disabled = false, render }) { const { sbcAppKit, refreshAccount } = useSbcApp(); const [isConnecting, setIsConnecting] = react.useState(false); const [error, setError] = react.useState(null); const handleConnect = async () => { if (!sbcAppKit || isConnecting || disabled) return; try { setIsConnecting(true); setError(null); const result = await sbcAppKit.connectWallet(walletType); await refreshAccount(); onConnect?.(result); } catch (err) { const error2 = err instanceof Error ? err : new Error("Failed to connect wallet"); if (sbcAppKit.debug) { console.error("[SBC App Kit] Wallet connection failed:", error2); console.error("[SBC App Kit] Wallet type:", walletType); } setError(error2.message); onError?.(error2); } finally { setIsConnecting(false); } }; const getButtonText = () => { if (children) return children; if (isConnecting) return "Connecting..."; if (walletType === "metamask") return "Connect MetaMask"; if (walletType === "coinbase") return "Connect Coinbase Wallet"; if (walletType === "walletconnect") return "Connect WalletConnect"; return "Connect Wallet"; }; const baseStyles = ` px-4 py-2 rounded-md font-medium transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed `.trim(); const stateStyles = isConnecting || disabled ? "bg-gray-300 text-gray-600 cursor-not-allowed" : "bg-blue-600 text-white hover:bg-blue-700 active:bg-blue-800"; const finalClassName = `${baseStyles} ${stateStyles} ${className}`.trim(); if (render) { return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [ render({ onClick: handleConnect, isConnecting, disabled: isConnecting || disabled || !sbcAppKit, children: getButtonText(), className: finalClassName }), error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2", children: error }) ] }); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [ /* @__PURE__ */ jsxRuntime.jsxs( "button", { type: "button", className: finalClassName, onClick: handleConnect, disabled: isConnecting || disabled || !sbcAppKit, children: [ showLoading && isConnecting && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-4 h-4 mr-2 animate-spin rounded-full border-2 border-transparent border-t-current" }), getButtonText() ] } ), error && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-red-600 bg-red-50 border border-red-200 rounded px-3 py-2", children: error }) ] }); } function WalletSelector({ className = "", onConnect, onError, showOnlyAvailable = true, wallets: customWallets }) { const { sbcAppKit } = useSbcContext(); const [availableWallets, setAvailableWallets] = react.useState([]); const [isLoading, setIsLoading] = react.useState(true); const [connectingWallet, setConnectingWallet] = react.useState(null); react.useEffect(() => { const loadWallets = async () => { if (!sbcAppKit) return; try { setIsLoading(true); if (sbcAppKit.getAvailableWallets) { const wallets = await sbcAppKit.getAvailableWallets(); setAvailableWallets(wallets); } else { const fallbackWallets = [ { type: "metamask", name: "MetaMask", available: typeof window !== "undefined" && !!window.ethereum, icon: "https://docs.metamask.io/img/metamask-fox.svg" }, { type: "coinbase", name: "Coinbase Wallet", available: typeof window !== "undefined" && !!(window.ethereum || window.coinbaseWalletExtension), icon: "https://wallet-api-production.s3.amazonaws.com/uploads/tokens/eth_288.png" }, { type: "walletconnect", name: "WalletConnect", available: true, icon: "https://registry.walletconnect.com/api/v1/logo/sm/walletconnect.png" } ]; setAvailableWallets(fallbackWallets); } } catch (error) { console.error("Failed to load available wallets:", error); setAvailableWallets([]); } finally { setIsLoading(false); } }; loadWallets(); }, [sbcAppKit]); const handleWalletConnect = async (walletType) => { if (!sbcAppKit || connectingWallet) return; try { setConnectingWallet(walletType); if (sbcAppKit.connectWallet) { const result = await sbcAppKit.connectWallet(walletType); onConnect?.(result); } else { throw new Error("Wallet integration coming soon! Use the dev:local script to test with the latest SDK features."); } } catch (err) { const error = err instanceof Error ? err : new Error("Failed to connect wallet"); onError?.(error); } finally { setConnectingWallet(null); } }; const walletsToShow = customWallets || availableWallets; const filteredWallets = showOnlyAvailable ? walletsToShow.filter((w) => w.available) : walletsToShow; if (isLoading) { return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `space-y-4 ${className}`, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-gray-600", children: [ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "inline-block w-6 h-6 animate-spin rounded-full border-2 border-gray-300 border-t-blue-600" }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2", children: "Detecting available wallets..." }) ] }) }); } if (filteredWallets.length === 0) { return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `text-center p-6 bg-gray-50 border border-gray-200 rounded-lg ${className}`, children: [ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-gray-600 mb-4", children: "No compatible wallets found." }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: "Please install MetaMask, Coinbase Wallet, or use WalletConnect to continue." }) ] }); } return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `space-y-3 ${className}`, children: [ /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-medium text-gray-900 mb-4", children: "Connect Wallet" }), filteredWallets.map((wallet) => /* @__PURE__ */ jsxRuntime.jsxs( "button", { type: "button", className: ` w-full flex items-center justify-between p-4 border rounded-lg transition-colors ${wallet.available ? "border-gray-200 hover:border-blue-300 hover:bg-blue-50 focus:border-blue-500 focus:ring-2 focus:ring-blue-200" : "border-gray-100 bg-gray-50 cursor-not-allowed opacity-60"} ${connectingWallet === wallet.type ? "border-blue-500 bg-blue-50" : ""} `, onClick: () => handleWalletConnect(wallet.type), disabled: !wallet.available || connectingWallet !== null, children: [ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center space-x-3", children: [ wallet.icon && /* @__PURE__ */ jsxRuntime.jsx( "img", { src: wallet.icon, alt: `${wallet.name} icon`, className: "w-8 h-8 rounded", onError: (e) => { e.target.style.display = "none"; } } ), /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-left", children: [ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "font-medium text-gray-900", children: wallet.name }), /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-500", children: wallet.available ? "Ready to connect" : "Not installed" }) ] }) ] }), /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center", children: connectingWallet === wallet.type ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-5 h-5 animate-spin rounded-full border-2 border-blue-600 border-t-transparent" }) : wallet.available ? /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-gray-400", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M9 5l7 7-7 7" }) }) : /* @__PURE__ */ jsxRuntime.jsx("svg", { className: "w-5 h-5 text-gray-300", fill: "none", stroke: "currentColor", viewBox: "0 0 24 24", children: /* @__PURE__ */ jsxRuntime.jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) }) }) ] }, wallet.type )) ] }); } exports.SbcProvider = SbcProvider; exports.WalletButton = WalletButton; exports.WalletConnect = WalletConnect; exports.WalletSelector = WalletSelector; exports.useSbcApp = useSbcApp; exports.useSbcContext = useSbcContext; exports.useSbcDynamic = useSbcDynamic; exports.useSbcPara = useSbcPara; exports.useSbcTurnkey = useSbcTurnkey; exports.useUserOperation = useUserOperation;