From 86ff43e20625631a0c76fd719c30ce301e0a02fa Mon Sep 17 00:00:00 2001 From: Kurdistan Tech Ministry Date: Mon, 27 Apr 2026 13:31:22 +0300 Subject: [PATCH] feat: write p2p_user_id to tg_users on Telegram wallet link TelegramConnect: query tg_users instead of users, resolve visa UUID from p2p_visa table and store as p2p_user_id for cross-platform P2P. P2PIdentityContext: when citizen resolves their UUID, backfill tg_users.p2p_user_id if their wallet is linked to a Telegram account. --- web/src/contexts/P2PIdentityContext.tsx | 15 ++++++++++++ web/src/pages/TelegramConnect.tsx | 32 +++++++++++++++++++++---- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/web/src/contexts/P2PIdentityContext.tsx b/web/src/contexts/P2PIdentityContext.tsx index d5aa69eb..b8e55318 100644 --- a/web/src/contexts/P2PIdentityContext.tsx +++ b/web/src/contexts/P2PIdentityContext.tsx @@ -54,6 +54,21 @@ export function P2PIdentityProvider({ children }: { children: ReactNode }) { const uuid = await identityToUUID(fullCitizenNumber); setUserId(uuid); setVisaNumber(null); + + // If this wallet is linked to a Telegram account and p2p_user_id not set yet, + // backfill it so mini app users see the same P2P identity + if (walletAddress) { + supabase + .from('tg_users') + .select('id, p2p_user_id') + .eq('wallet_address', walletAddress) + .maybeSingle() + .then(({ data: tgUser }) => { + if (tgUser && !tgUser.p2p_user_id) { + supabase.from('tg_users').update({ p2p_user_id: uuid }).eq('id', tgUser.id); + } + }); + } } else if (walletAddress) { // Non-citizen: check for existing visa const { data: visa } = await supabase diff --git a/web/src/pages/TelegramConnect.tsx b/web/src/pages/TelegramConnect.tsx index 7ef62143..39f4a5dc 100644 --- a/web/src/pages/TelegramConnect.tsx +++ b/web/src/pages/TelegramConnect.tsx @@ -6,6 +6,7 @@ import { useEffect, useState } from 'react'; import { useNavigate, useSearchParams } from 'react-router-dom'; import { supabase } from '@/lib/supabase'; +import { identityToUUID } from '@shared/lib/identity'; import { Loader2, AlertTriangle, CheckCircle2 } from 'lucide-react'; import { useTranslation } from 'react-i18next'; @@ -51,8 +52,8 @@ export default function TelegramConnect() { // Find user by telegram_id const { data: userData, error: userError } = await supabase - .from('users') - .select('id, telegram_id, wallet_address, username, first_name') + .from('tg_users') + .select('id, telegram_id, wallet_address, p2p_user_id') .eq('telegram_id', parseInt(telegramId, 10)) .single(); @@ -62,11 +63,32 @@ export default function TelegramConnect() { return; } - // Update wallet address if provided and different + // Update wallet address and resolve p2p_user_id if not already set + const updates: Record = {}; if (walletAddress && walletAddress !== userData.wallet_address) { + updates.wallet_address = walletAddress; + } + + if (!userData.p2p_user_id && walletAddress) { + // Try to find visa linked to this wallet (non-citizen users) + const { data: visa } = await supabase + .from('p2p_visa') + .select('visa_number') + .eq('wallet_address', walletAddress) + .eq('status', 'active') + .maybeSingle(); + + if (visa?.visa_number) { + updates.p2p_user_id = await identityToUUID(visa.visa_number); + } + // Welati (citizen) users: p2p_user_id will be set when they visit pwap/web P2P + // with their wallet connected (see P2PIdentityContext → linkTelegramP2PIdentity) + } + + if (Object.keys(updates).length > 0) { await supabase - .from('users') - .update({ wallet_address: walletAddress }) + .from('tg_users') + .update(updates) .eq('id', userData.id); }