feat: unified P2P identity across Telegram mini app and pwap/web

Add p2p_user_id column to tg_users to bridge citizen/visa UUID (v5)
used by pwap/web with the Supabase Auth UUID (v4) used by the mini app.

- Migration: tg_users.p2p_user_id UUID (nullable, indexed)
- 6 P2P edge functions: replace listUsers+find with direct tg_users
  lookup — resolves userId as p2p_user_id ?? id (backwards compatible)
- Eliminates O(N) auth.admin.listUsers scan in every P2P call

When p2p_user_id is populated (via TelegramConnect wallet link),
mini app users share the same P2P balance and offers as pwap/web.
This commit is contained in:
2026-04-27 13:30:09 +03:00
parent faf0faed69
commit 698c014682
9 changed files with 245 additions and 152 deletions
@@ -160,21 +160,22 @@ serve(async (req) => {
const supabaseServiceKey = Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!;
const supabase = createClient(supabaseUrl, supabaseServiceKey);
// Get auth user ID for this telegram user
const telegramEmail = `telegram_${telegramId}@pezkuwichain.io`;
const {
data: { users: authUsers },
} = await supabase.auth.admin.listUsers({ perPage: 1000 });
const authUser = authUsers?.find((u: { email?: string }) => u.email === telegramEmail);
// Resolve P2P user ID: prefer p2p_user_id (citizen/visa UUID, same as pwap/web)
// fallback to tg_users.id (legacy Supabase Auth UUID)
const { data: tgUser, error: tgUserError } = await supabase
.from('tg_users')
.select('id, p2p_user_id')
.eq('telegram_id', telegramId)
.single();
if (!authUser) {
if (tgUserError || !tgUser) {
return new Response(JSON.stringify({ error: 'User not found. Please authenticate first.' }), {
status: 404,
headers: { ...corsHeaders, 'Content-Type': 'application/json' },
});
}
const userId = authUser.id;
const userId = tgUser.p2p_user_id ?? tgUser.id;
// 1. Lock escrow from internal balance
const { data: lockResult, error: lockError } = await supabase.rpc('lock_escrow_internal', {