'use client'; import { useCallback, useState } from 'react'; import { SignIn as SignInCore } from '@farcaster/miniapp-sdk'; import { useQuickAuth } from '~/hooks/useQuickAuth'; import { Button } from '../Button'; /** * SignIn component handles Farcaster authentication using QuickAuth. * * This component provides a complete authentication flow for Farcaster users: * - Uses the built-in QuickAuth functionality from the Farcaster SDK * - Manages authentication state in memory (no persistence) * - Provides sign-out functionality * - Displays authentication status and results * * The component integrates with the Farcaster Frame SDK and QuickAuth * to provide seamless authentication within mini apps. * * @example * ```tsx * * ``` */ interface AuthState { signingIn: boolean; signingOut: boolean; } export function SignIn() { // --- State --- const [authState, setAuthState] = useState({ signingIn: false, signingOut: false, }); const [signInFailure, setSignInFailure] = useState(); // --- Hooks --- const { authenticatedUser, status, signIn, signOut } = useQuickAuth(); // --- Handlers --- /** * Handles the sign-in process using QuickAuth. * * This function uses the built-in QuickAuth functionality: * 1. Gets a token from QuickAuth (handles SIWF flow automatically) * 2. Validates the token with our server * 3. Updates the session state * * @returns Promise */ const handleSignIn = useCallback(async () => { try { setAuthState(prev => ({ ...prev, signingIn: true })); setSignInFailure(undefined); const success = await signIn(); if (!success) { setSignInFailure('Authentication failed'); } } catch (e) { if (e instanceof SignInCore.RejectedByUser) { setSignInFailure('Rejected by user'); return; } setSignInFailure('Unknown error'); } finally { setAuthState(prev => ({ ...prev, signingIn: false })); } }, [signIn]); /** * Handles the sign-out process. * * This function clears the QuickAuth session and resets the local state. * * @returns Promise */ const handleSignOut = useCallback(async () => { try { setAuthState(prev => ({ ...prev, signingOut: true })); await signOut(); } finally { setAuthState(prev => ({ ...prev, signingOut: false })); } }, [signOut]); // --- Render --- return ( <> {/* Authentication Buttons */} {status !== 'authenticated' && ( Sign In with Farcaster )} {status === 'authenticated' && ( Sign out )} {/* Session Information */} {authenticatedUser && ( Authenticated User {JSON.stringify(authenticatedUser, null, 2)} )} {/* Error Display */} {signInFailure && !authState.signingIn && ( Authentication Error {signInFailure} )} > ); }