/** * Telegram Mini App Connect Page * Handles authentication from Telegram mini app and redirects to P2P */ import { useEffect, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { supabase } from '@/lib/supabase'; import { Loader2, AlertTriangle, CheckCircle2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; type Status = 'loading' | 'connecting' | 'success' | 'error'; export default function TelegramConnect() { const [searchParams] = useSearchParams(); const navigate = useNavigate(); const { t } = useTranslation(); const [status, setStatus] = useState('loading'); const [message, setMessage] = useState(t('telegramConnect.connecting')); const [error, setError] = useState(null); useEffect(() => { const connect = async () => { try { // Get params from URL const telegramId = searchParams.get('tg_id'); const walletAddress = searchParams.get('wallet'); const timestamp = searchParams.get('ts'); const from = searchParams.get('from'); // Validate params if (!telegramId || from !== 'miniapp') { setStatus('error'); setError(t('telegramConnect.invalidParams')); return; } // Check timestamp (allow 5 minutes) if (timestamp) { const ts = parseInt(timestamp, 10); const now = Date.now(); if (now - ts > 5 * 60 * 1000) { setStatus('error'); setError(t('telegramConnect.linkExpired')); return; } } setStatus('connecting'); setMessage(t('telegramConnect.authenticating')); // Find user by telegram_id const { data: userData, error: userError } = await supabase .from('users') .select('id, telegram_id, wallet_address, username, first_name') .eq('telegram_id', parseInt(telegramId, 10)) .single(); if (userError || !userData) { setStatus('error'); setError(t('telegramConnect.userNotFound')); return; } // Update wallet address if provided and different if (walletAddress && walletAddress !== userData.wallet_address) { await supabase .from('users') .update({ wallet_address: walletAddress }) .eq('id', userData.id); } // Generate email for this telegram user (for Supabase auth) const telegramEmail = `telegram_${telegramId}@pezkuwichain.io`; // Try to sign in with magic link (will be sent to email, but we'll catch it) // Or check if user already has an auth account const { data: authData } = await supabase.auth.getSession(); if (authData?.session) { // Already logged in, redirect to P2P setStatus('success'); setMessage(t('telegramConnect.success')); setTimeout(() => navigate('/p2p'), 1000); return; } // Try to sign in with OTP/magic link const { error: signInError } = await supabase.auth.signInWithOtp({ email: telegramEmail, options: { shouldCreateUser: true, data: { telegram_id: parseInt(telegramId, 10), wallet_address: walletAddress, username: userData.username || userData.first_name, }, }, }); if (signInError) { // If OTP fails, try password-less sign in console.error('OTP sign in failed:', signInError); // Store telegram session info in localStorage for P2P access localStorage.setItem('telegram_session', JSON.stringify({ telegram_id: telegramId, wallet_address: walletAddress, username: userData.username || userData.first_name, timestamp: Date.now(), })); setStatus('success'); setMessage(t('telegramConnect.success')); setTimeout(() => navigate('/p2p'), 1000); return; } // Success - redirect to P2P setStatus('success'); setMessage(t('telegramConnect.success')); setTimeout(() => navigate('/p2p'), 1000); } catch (err) { console.error('Telegram connect error:', err); setStatus('error'); setError(t('telegramConnect.connectionError')); } }; connect(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [searchParams, navigate]); return (
{/* Logo */}
{status === 'loading' || status === 'connecting' ? ( ) : status === 'success' ? ( ) : ( )}
{/* Title */}

{status === 'error' ? t('telegramConnect.errorTitle') : t('telegramConnect.title')}

{/* Status Message */}

{error || message}

{/* Error Action */} {status === 'error' && (

{t('telegramConnect.returnToMiniApp')}

)} {/* Success Info */} {status === 'success' && (
{t('telegramConnect.openingP2P')}
)}
); }