From 30c47b99e90002da736a544a2e7a9c1abf35b3e0 Mon Sep 17 00:00:00 2001 From: memosr Date: Wed, 3 Jun 2026 11:18:04 +0300 Subject: [PATCH] fix: verify wallet ownership in bridge estimate and rebalance --- app/api/bridge/estimate/route.ts | 30 ++++++++++++++++++++++++++++++ app/api/bridge/rebalance/route.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+) diff --git a/app/api/bridge/estimate/route.ts b/app/api/bridge/estimate/route.ts index 6df7c10..7fdf3b1 100644 --- a/app/api/bridge/estimate/route.ts +++ b/app/api/bridge/estimate/route.ts @@ -89,6 +89,36 @@ export async function POST(request: NextRequest) { ); } + // Verify source wallet belongs to the authenticated user + const { data: sourceWalletOwnership, error: sourceOwnershipError } = await supabase + .from("wallets") + .select("circle_wallet_id") + .eq("user_id", user.id) + .eq("circle_wallet_id", sourceWalletId) + .single(); + + if (sourceOwnershipError || !sourceWalletOwnership) { + return NextResponse.json( + { error: "Source wallet not found or access denied" }, + { status: 404 } + ); + } + + // Verify destination wallet belongs to the authenticated user + const { data: destWalletOwnership, error: destOwnershipError } = await supabase + .from("wallets") + .select("circle_wallet_id") + .eq("user_id", user.id) + .eq("circle_wallet_id", destinationWalletId) + .single(); + + if (destOwnershipError || !destWalletOwnership) { + return NextResponse.json( + { error: "Destination wallet not found or access denied" }, + { status: 404 } + ); + } + // Get source wallet address const sourceWalletResponse = await circleDeveloperSdk.getWallet({ id: sourceWalletId, diff --git a/app/api/bridge/rebalance/route.ts b/app/api/bridge/rebalance/route.ts index 7a2984a..bf79f7b 100644 --- a/app/api/bridge/rebalance/route.ts +++ b/app/api/bridge/rebalance/route.ts @@ -100,6 +100,36 @@ export async function POST(request: NextRequest) { ); } + // Verify source wallet belongs to the authenticated user + const { data: sourceWalletOwnership, error: sourceOwnershipError } = await supabase + .from("wallets") + .select("circle_wallet_id") + .eq("user_id", user.id) + .eq("circle_wallet_id", sourceWalletId) + .single(); + + if (sourceOwnershipError || !sourceWalletOwnership) { + return NextResponse.json( + { error: "Source wallet not found or access denied" }, + { status: 404 } + ); + } + + // Verify destination wallet belongs to the authenticated user + const { data: destWalletOwnership, error: destOwnershipError } = await supabase + .from("wallets") + .select("circle_wallet_id") + .eq("user_id", user.id) + .eq("circle_wallet_id", destinationWalletId) + .single(); + + if (destOwnershipError || !destWalletOwnership) { + return NextResponse.json( + { error: "Destination wallet not found or access denied" }, + { status: 404 } + ); + } + // Get source wallet address const sourceWalletResponse = await circleDeveloperSdk.getWallet({ id: sourceWalletId,