Last Working Commit: 6984f2f (February 3, 2026)
Branch: main
Deployment: Vercel (xmerch-polluxchess.vercel.app)
Network: Xahau Testnet (NetworkID 21337)
- User clicks "Connect with Xaman"
- QR popup opens
- User scans with Xaman mobile app
- Signs in successfully
- Popup closes
- User logged in, playerID saved to localStorage
Status: β FULLY WORKING
- User selects tournament fee (e.g., 10 XAH)
- Clicks Submit
- Xaman QR popup opens
- User scans and signs payment
- WebSocket detects
tesSUCCESS - Webhook fires successfully
- Player added to
tournament_playerstable in Supabase
Status: β PAYMENT PROCESSING WORKS
- Testnet NetworkID: 21337 β
- Mainnet NetworkID: 21338 β
- Hook Address (Testnet): rpbvh5LmrV17BVCu5fAc1ybKev1pFa8evh β
Status: β NETWORK IDS CORRECT
Symptom:
- Payment succeeds
- Webhook adds player to tournament
- Join API returns 409 "Player already in tournament" with tournamentId
- BUT: Page does NOT redirect to waiting room
- User stuck on
/chesspage - If manually navigating to waiting room: "Security error: unable to verify wallet"
Console Logs Show:
π‘ Join API response status: 409
β οΈ Player already in tournament: 9fc71e42-4f12-4627-9a3b-773ff4bae6bb
[No redirect happens - page stays on /chess]
Expected Behavior:
Should redirect to: /waiting-room?tournamentId=9fc71e42-4f12-4627-9a3b-773ff4bae6bb&uuid=6f2b07c2-e12c-4aa8-bff7-61ca06e38e93
Root Cause: The 409 handler in the desktop payment flow is logging the message but NOT executing the redirect.
File: app/chess/page.tsx (1400+ lines)
Desktop Payment Handler (around line 1100-1200):
// After payment succeeds via WebSocket:
console.log("β
Payment confirmed ON LEDGER - now joining tournament...")
const joinRes = await fetch('/api/tournaments/join', {...})
console.log("π‘ Join API response status:", joinRes.status)
// β
Handle 409 "already in tournament" BEFORE checking ok status
if (joinRes.status === 409) {
const joinData = await joinRes.json()
if (joinData.tournamentId) {
console.log("β οΈ Player already in tournament:", joinData.tournamentId)
alert("You're already in a tournament!\n\nRedirecting...")
// π¨ THIS REDIRECT IS NOT EXECUTING:
window.location.href = `/waiting-room?tournamentId=${joinData.tournamentId}`
return
}
}Status: Code looks correct but redirect fails. Unknown blocker.
1. xaman-signinPayload/index.ts
- NetworkID: β Correct (testnet=21337, mainnet=21338)
- Status: β WORKING
2. xaman-createPayload/index.ts
- NetworkID: β Correct (testnet=21337, mainnet=21338)
- Return URL: β Includes web + app properties
- Status: β WORKING
3. xaman-webhook/index.ts
- Processes payments successfully
- Adds players to
tournament_playerstable - Status: β WORKING
4. xaman-getPayload/index.ts
- Returns full payload data for verification
- Status: β WORKING (but not being used effectively)
File: app/waiting-room/page.tsx
Current Verification Logic:
async function verifyWallet() {
// 1. Checks tournament_players table (5 retries, 800ms delay)
// 2. Falls back to Xaman payload status if uuid provided
// 3. If both fail: "Security error: unable to verify wallet"
}Problem:
- User never reaches waiting room (redirect blocked)
- If manually navigating, verification fails because:
- No
uuidin URL (wasn't passed in redirect) - DB query racing (might be too fast)
- No
Status: β NOT WORKING due to upstream redirect issue
tournament_players
- Contains stuck entries with status="joined"
- Player: rhAaDqi8tqd2f4HJbAwqUHs6VdQrktppmh
- Tournament ID: 9fc71e42-4f12-4627-9a3b-773ff4bae6bb
tournaments
- Status: "waiting"
- Tournament size: 2
- Entry fee: 10 XAH
Problem: Data is correct in database, but frontend can't access waiting room.
- Fixed in both Supabase functions
- Deployed to Supabase
// Before: addDebug`URL: ...`)
// After: addDebug(`URL: ...`)- Increased from 1000ms to 2000ms
- Added "Waiting for database to commit..." log
- Removed unreachable setTimeout after redirect
- Now defaults to
/chessinstead of/waiting-room - Includes both web + app properties
/app/api/auth/xaman/get-payload/xahau-payload/route.ts
// Before: reject(new Error`...`)
// After: throw new Error(`...`)- Replaced direct
createClient()calls with singletongetSupabaseClient() - Updated: app/chess/page.tsx, lib/auth/session-manager.ts
- Added 409 check before !ok check in both mobile join blocks
- Added uuid parameter to waiting-room redirects
- Added Xaman payload status verification fallback
- Status: Not working because redirect never happens
The 409 redirect is being blocked or ignored.
Possible causes:
- JavaScript execution blocked by alert()?
- React state update preventing navigation?
- Event handler not completing?
- Window.location.href being overridden?
- Page remounting after alert clears?
Need to investigate:
if (joinRes.status === 409) {
const joinData = await joinRes.json()
if (joinData.tournamentId) {
console.log("β οΈ Player already in tournament:", joinData.tournamentId)
alert("You're already in a tournament!\n\nRedirecting...") // β Does this block?
window.location.href = `/waiting-room?tournamentId=${joinData.tournamentId}` // β Never executes
return
}
}Add more logging:
if (joinRes.status === 409) {
console.log("π [DEBUG] Entered 409 handler")
const joinData = await joinRes.json()
console.log("π [DEBUG] Join data:", joinData)
if (joinData.tournamentId) {
console.log("π [DEBUG] About to show alert")
alert("You're already in a tournament!\n\nRedirecting...")
console.log("π [DEBUG] Alert dismissed, about to redirect")
const redirectUrl = `/waiting-room?tournamentId=${joinData.tournamentId}`
console.log("π [DEBUG] Redirect URL:", redirectUrl)
window.location.href = redirectUrl
console.log("π [DEBUG] Redirect called")
return
}
}// Option A: Remove alert, try immediate redirect
window.location.href = `/waiting-room?tournamentId=${joinData.tournamentId}`
// Option B: Use replace instead of href
window.location.replace(`/waiting-room?tournamentId=${joinData.tournamentId}`)
// Option C: Use Next.js router
// (would need to pass router instance to function)
router.push(`/waiting-room?tournamentId=${joinData.tournamentId}`)Look for:
- Any state updates after the redirect call
- useEffect hooks that might remount component
- Error boundaries catching navigation
Remove alert completely:
if (joinRes.status === 409) {
const joinData = await joinRes.json()
if (joinData.tournamentId) {
console.log("β
Tournament found, redirecting immediately...")
window.location.replace(`/waiting-room?tournamentId=${joinData.tournamentId}&uuid=${paymentUuid}`)
return
}
}If new AI breaks things, rollback to this commit:
# Rollback frontend code
git checkout 6984f2f
# Verify commit
git log --oneline -1
# Should show:
# 6984f2f fix: correct Error constructor syntax on line 466
# Rebuild
pnpm build
# Deploy
git push origin main --force # Only if neededSupabase Functions Status: Already deployed with correct Network IDs. No rollback needed unless you modify them.
Before considering any fix "working":
- Login works
- Payment QR opens
- Sign in Xaman
- Payment succeeds (check console: "tesSUCCESS")
- Join API called (check console: "Sending join request")
- CRITICAL: Page redirects to
/waiting-room?tournamentId=... - Waiting room loads without security error
- Player sees "Waiting for opponent" message
- Check
tournament_players- player row exists with status="joined" - Check
tournaments- tournament exists with status="waiting" - Check
hook_logs- payment logged with correct amount
- Waiting room URL includes
tournamentIdparameter - Waiting room URL includes
uuidparameter (optional but helpful)
NEXT_PUBLIC_BASE_URL=https://xmerch-polluxchess.vercel.app
NEXT_PUBLIC_SUPABASE_URL=https://kijlhftinrufbuigostz.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
NEXT_PUBLIC_XAHAU_NETWORK_ID=21337 # Testnet
NEXT_PUBLIC_HOOK_ADDRESS_MAINNET=rYOUR_MAINNET_HOOKXUMM_API_KEY=your-xaman-api-key
XUMM_API_SECRET=your-xaman-api-secret
XAH_DESTINATION_TESTNET=rpbvh5LmrV17BVCu5fAc1ybKev1pFa8evh
XAH_DESTINATION_MAINNET=rYOUR_MAINNET_HOOK
SB_URL=https://kijlhftinrufbuigostz.supabase.co
SB_SERVICE_ROLE_KEY=your-service-role-key
NEXT_PUBLIC_SITE_URL=https://xmerch-polluxchess.vercel.app-- Clean test data
DELETE FROM tournament_players
WHERE player_address = 'rhAaDqi8tqd2f4HJbAwqUHs6VdQrktppmh';
DELETE FROM tournaments
WHERE id IN (
SELECT DISTINCT tournament_id
FROM tournament_players
WHERE player_address = 'rhAaDqi8tqd2f4HJbAwqUHs6VdQrktppmh'
);
-- Verify cleanup
SELECT * FROM tournament_players WHERE player_address = 'rhAaDqi8tqd2f4HJbAwqUHs6VdQrktppmh';
-- Should return 0 rowsSingle objective: Fix the 409 redirect so users can enter the waiting room after successful payment.
Success criteria:
- Payment succeeds β (already works)
- Join API returns 409 β (already works)
- Page redirects to waiting room β (BROKEN - FIX THIS)
- Waiting room verification succeeds
β οΈ (blocked by #3)
Focus area:
app/chess/page.tsx lines ~1150-1170 (desktop payment 409 handler)
Do NOT:
- Change Network IDs (already correct)
- Modify webhook logic (working fine)
- Refactor unrelated code
- Change database schema
DO:
- Debug why
window.location.hrefisn't executing - Test alternative redirect methods
- Add comprehensive logging
- Remove alert if it's blocking navigation
Previous README: READMExamandocs.md
Fix Instructions: CLINE_FIX_INSTRUCTIONS.md
Xaman Integration: All 50+ docs read and applied
Key Xaman Patterns Used:
- WebSocket for transaction monitoring β
- Return URLs for mobile redirect β
- NetworkID in payload β
- Webhook for server-side verification β
- Read this file completely
- Read READMExamandocs.md for architecture context
- Focus on the 409 redirect bug (lines 1150-1170 in app/chess/page.tsx)
- Add debug logging first - don't change logic yet
- Test on desktop (easier to debug than mobile)
- Verify redirect happens before touching waiting room logic
Last Updated: February 4, 2026
Status: Payment works, redirect broken, waiting for fix
Priority: HIGH - blocking users from playing games
# Nuclear option - full rollback
git reset --hard 6984f2f
git clean -fd
pnpm install
pnpm build
# Redeploy Supabase functions (just in case)
cd supabase/functions
supabase functions deploy xaman-signinPayload
supabase functions deploy xaman-createPayload
supabase functions deploy xaman-webhookThis should restore to the "payment works but no redirect" state.
END OF ROLLBACK README