import { serve } from 'https://deno.land/std@0.177.0/http/server.ts'; import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'; import { createHmac } from 'https://deno.land/std@0.177.0/node/crypto.ts'; const ALLOWED_ORIGINS = ['https://telegram.pezkuwichain.io', 'https://telegram.pezkiwi.app']; function getCorsHeaders(origin?: string | null): Record { const allowedOrigin = origin && ALLOWED_ORIGINS.some((o) => origin.startsWith(o)) ? origin : ALLOWED_ORIGINS[0]; return { 'Access-Control-Allow-Origin': allowedOrigin, 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type, x-supabase-client-platform', 'Access-Control-Allow-Methods': 'POST, OPTIONS', }; } interface TelegramUser { id: number; first_name: string; last_name?: string; username?: string; } function validateInitData(initData: string, botToken: string): TelegramUser | null { try { const params = new URLSearchParams(initData); const hash = params.get('hash'); if (!hash) return null; params.delete('hash'); const sortedParams = Array.from(params.entries()) .sort(([a], [b]) => a.localeCompare(b)) .map(([key, value]) => `${key}=${value}`) .join('\n'); const secretKey = createHmac('sha256', 'WebAppData').update(botToken).digest(); const calculatedHash = createHmac('sha256', secretKey).update(sortedParams).digest('hex'); if (calculatedHash !== hash) return null; const authDate = parseInt(params.get('auth_date') || '0'); const now = Math.floor(Date.now() / 1000); if (now - authDate > 86400) return null; const userStr = params.get('user'); if (!userStr) return null; return JSON.parse(userStr) as TelegramUser; } catch { return null; } } serve(async (req) => { const origin = req.headers.get('origin'); const corsHeaders = getCorsHeaders(origin); if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { const body = await req.json(); const { initData } = body; if (!initData) { return new Response(JSON.stringify({ error: 'Missing initData' }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } const supabaseUrl = Deno.env.get('SUPABASE_URL')!; const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!; const botTokens: string[] = []; const _mainToken = Deno.env.get('TELEGRAM_BOT_TOKEN'); const _krdToken = Deno.env.get('TELEGRAM_BOT_TOKEN_KRD'); if (_mainToken) botTokens.push(_mainToken); if (_krdToken) botTokens.push(_krdToken); if (botTokens.length === 0) { return new Response(JSON.stringify({ error: 'Server configuration error' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } let telegramUser: TelegramUser | null = null; for (const bt of botTokens) { telegramUser = validateInitData(initData, bt); if (telegramUser) break; } if (!telegramUser) { return new Response(JSON.stringify({ error: 'Invalid Telegram data' }), { status: 401, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } const supabase = createClient(supabaseUrl, supabaseServiceKey, { auth: { autoRefreshToken: false, persistSession: false }, }); // Get user const { data: user } = await supabase .from('tg_users') .select('id') .eq('telegram_id', telegramUser.id) .single(); if (!user) { return new Response(JSON.stringify({ deposits: [] }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } // Get deposits const { data: deposits } = await supabase .from('tg_deposits') .select('id, network, amount, status, tx_hash, created_at') .eq('user_id', user.id) .order('created_at', { ascending: false }) .limit(20); return new Response(JSON.stringify({ deposits: deposits || [] }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } catch { return new Response(JSON.stringify({ error: 'Internal server error' }), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } });