import React, { useState } from 'react'; import { Button } from '@/components/ui/button'; import { Input } from '@/components/ui/input'; import { Label } from '@/components/ui/label'; import { Alert, AlertDescription } from '@/components/ui/alert'; import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'; import { Loader2, CheckCircle, AlertTriangle, Shield } from 'lucide-react'; import { usePezkuwi } from '@/contexts/PezkuwiContext'; import { verifyCitizenNumber } from '@pezkuwi/lib/tiki'; import { generateAuthChallenge, signChallenge, verifySignature, saveCitizenSession } from '@pezkuwi/lib/citizenship-workflow'; import type { AuthChallenge } from '@pezkuwi/lib/citizenship-workflow'; interface ExistingCitizenAuthProps { onClose: () => void; } export const ExistingCitizenAuth: React.FC = ({ onClose }) => { const { api, isApiReady, selectedAccount, connectWallet } = usePezkuwi(); const [citizenNumber, setCitizenNumber] = useState(''); const [step, setStep] = useState<'input' | 'verifying' | 'signing' | 'success' | 'error'>('input'); const [error, setError] = useState(null); const [challenge, setChallenge] = useState(null); const handleVerifyNFT = async () => { if (!api || !isApiReady || !selectedAccount) { setError('Please connect your wallet first'); return; } if (!citizenNumber.trim()) { setError('Please enter your Citizen Number'); return; } setError(null); setStep('verifying'); try { // Verify Citizen Number const isValid = await verifyCitizenNumber(api, citizenNumber, selectedAccount.address); if (!isValid) { setError(`Invalid Citizen Number or it doesn't match your wallet`); setStep('error'); return; } // Generate challenge for signature const authChallenge = generateAuthChallenge(citizenNumber); setChallenge(authChallenge); setStep('signing'); } catch { if (process.env.NODE_ENV !== 'production') console.error('Verification error:', err); setError('Failed to verify Citizen Number'); setStep('error'); } }; const handleSignChallenge = async () => { if (!selectedAccount || !challenge) { setError('Missing authentication data'); return; } setError(null); try { // Sign the challenge const signature = await signChallenge(selectedAccount, challenge); // Verify signature (self-verification for demonstration) const isValid = await verifySignature(signature, challenge, selectedAccount.address); if (!isValid) { setError('Signature verification failed'); setStep('error'); return; } // Save session const session = { tikiNumber: citizenNumber, walletAddress: selectedAccount.address, sessionToken: signature, // In production, use proper JWT lastAuthenticated: Date.now(), expiresAt: Date.now() + (24 * 60 * 60 * 1000) // 24 hours }; await saveCitizenSession(session); setStep('success'); // Redirect to citizens page after 2 seconds setTimeout(() => { onClose(); window.location.href = '/citizens'; }, 2000); } catch { if (process.env.NODE_ENV !== 'production') console.error('Signature error:', err); setError('Failed to sign authentication challenge'); setStep('error'); } }; const handleConnectWallet = async () => { try { await connectWallet(); } catch { setError('Failed to connect wallet'); } }; return (
Authenticate as Citizen Enter your Citizen Number from your Dashboard to authenticate {/* Step 1: Enter Citizen Number */} {step === 'input' && ( <>
setCitizenNumber(e.target.value)} onKeyDown={(e) => e.key === 'Enter' && handleVerifyNFT()} />

Enter your full Citizen Number from your Dashboard (format: #CollectionID-ItemID-6digits)

{!selectedAccount ? ( ) : ( )} )} {/* Step 2: Verifying */} {step === 'verifying' && (

Verifying Citizen Number on blockchain...

)} {/* Step 3: Sign Challenge */} {step === 'signing' && ( <> NFT ownership verified! Now sign to prove you control this wallet.

Authentication Challenge:

{challenge?.nonce}

)} {/* Step 4: Success */} {step === 'success' && (

Authentication Successful!

Welcome back, Citizen #{citizenNumber}

Redirecting to citizen dashboard...

)} {/* Error State */} {error && ( {error} )} {step === 'error' && ( )}
{/* Security Info */}

Security Information

  • • Your NFT number is cryptographically verified on-chain
  • • Signature proves you control the wallet without revealing private keys
  • • Session expires after 24 hours for your security
  • • No personal data is transmitted or stored on-chain
); };