"use client"; import { useEffect, useState, useRef } from "react"; import Image from "next/image"; import OpenGames from "./OpenGames"; import GameModal from "./GameModal"; import { HowItWorksModal } from "./HowItWorksModal"; import YourGames from "./YourGames"; import { Bet } from "@/types/Bet"; import { fetchOpenBets, createBet, joinBet, getVaultByAddress } from "@/shared/solana_helpers"; import { ConnectedSolanaWallet, usePrivy, useSolanaWallets } from "@privy-io/react-auth"; import { RematchModal } from "./RematchModal"; export default function HeroSection() { const [isModalOpen, setIsModalOpen] = useState(false); const [isGameModalOpen, setIsGameModalOpen] = useState(false); const [bets, setBets] = useState([]); const [solWallet, setSolWallet] = useState(); const [myActiveBet, setMyActiveBet] = useState(); const [rematch, setRematch] = useState(false); const [lastActiveBet, setLastActiveBet] = useState(); const [rematchInProgress, setRematchInProgress] = useState(false); const [rematchTxError, setRematchTxError] = useState(false); const [rematchBetAddress, setRematchBetAddress] = useState(null); const { wallets, ready } = useSolanaWallets(); const { user } = usePrivy(); const iframeRef = useRef(null); useEffect(()=>{ if(rematch){ if(!lastActiveBet){ console.log(`last active bet was null, heres active bet ${myActiveBet}`); } const isOwner = lastActiveBet?.owner_id == user?.id; console.log(`rematch function ${isOwner ? "owner" : "joiner"} owner_id:${lastActiveBet?.owner_id}`); if(isOwner){ handleCreateRematch(); }else{ handleJoinRematch(); } } },[rematch]) const game_close_signal = (status: number) => { setRematch(status == 1); setMyActiveBet(undefined); }; const updateBets = async () => { if (!ready || wallets.length === 0) return; const wallet = wallets.find((_wallet) => _wallet.type === "solana") || wallets[0]; setSolWallet(wallet); const fetchedBets = await fetchOpenBets(wallet); const filteredBets = fetchedBets.filter((bet) => !(bet.owner_id && bet.joiner_id)); const filledBets = fetchedBets.filter((bet) => bet.owner_id && bet.joiner_id); const activeBet = filledBets.find((bet) => bet.owner_id === user?.id || bet.joiner_id === user?.id); if(rematch){ setMyActiveBet(undefined); return; } setBets(filteredBets); if (!myActiveBet && lastActiveBet?.address !== activeBet?.address) { setMyActiveBet(activeBet); setLastActiveBet(activeBet); } }; const handleCreateRematch = async () => { console.log('Creating rematch...'); if (!lastActiveBet || !solWallet) return; setRematchInProgress(true); setRematchTxError(false); try { // Step 1: Create new bet const tx = await createBet( solWallet, user?.id ?? "", lastActiveBet.wager, lastActiveBet.id, true ); console.log("Rematch created. Transaction ID:", tx); // Step 2: Inform backend of rematch link const set_response = await fetch( `https://vps.playpoolstudios.com/duelfi/api/set_rematch_address.php?address=${lastActiveBet.address}&rematch_address=${tx}` ); console.log(await set_response.text()); // Step 3: Poll until vault account is found const pollUntilFound = async ( maxRetries = 10, delayMs = 3000 ): Promise => { for (let i = 0; i < maxRetries; i++) { const vault = await getVaultByAddress(solWallet, tx); if (vault) return vault; console.log(`Waiting for vault account... (${i + 1}/${maxRetries})`); await new Promise(res => setTimeout(res, delayMs)); } return undefined; }; const newBetAcc = await pollUntilFound(); if (!newBetAcc) { console.error("Failed to retrieve new bet vault after retries."); setRematchTxError(true); } else { // Step 4: Set new active bet setMyActiveBet(newBetAcc); setLastActiveBet(newBetAcc); setRematch(false); } } catch (err) { console.error("Create rematch failed:", err); setRematchTxError(true); } finally { setRematchInProgress(false); } }; const handleJoinRematch = async () => { if (!lastActiveBet || !solWallet) return; try { const pollForRematchAddress = async ( maxRetries = 10, delayMs = 3000 ): Promise => { for (let i = 0; i < maxRetries; i++) { console.log(`Polling rematch address... (${i + 1}/${maxRetries})`); const response = await fetch( `https://vps.playpoolstudios.com/duelfi/api/get_rematch_address.php?address=${lastActiveBet.address}` ); const rematchAddress = (await response.text()).trim(); if (rematchAddress.length > 5) { console.log("Found rematch address:", rematchAddress); return rematchAddress; } await new Promise(res => setTimeout(res, delayMs)); } console.warn("Rematch address not found after max retries."); return null; }; const rematchAddress = await pollForRematchAddress(); if (!rematchAddress) return; const pollForVault = async ( address: string, maxRetries = 10, delayMs = 3000 ): Promise => { for (let i = 0; i < maxRetries; i++) { console.log(`Polling vault for address ${address}... (${i + 1}/${maxRetries})`); const vault = await getVaultByAddress(solWallet, address); if (vault) return vault; await new Promise(res => setTimeout(res, delayMs)); } console.warn("Vault not found after max retries."); return null; }; const rematchVault:Bet = await pollForVault(rematchAddress); if (rematchVault) { const tx = await joinBet(solWallet, user?.id!, rematchVault.id, rematchVault.address); setMyActiveBet(rematchVault); setLastActiveBet(rematchVault); setRematch(false); console.log("Rematch vault set as active."); } } catch (err) { console.error("Error during handleJoinRematch:", err); } }; // const handleJoinRematch = async () => { // console.log('rejoining rematch'); // if (!solWallet || !lastActiveBet?.owner_id || !lastActiveBet?.wager) return; // setRematchInProgress(true); // setRematchTxError(false); // const maxAttempts = 50; // let attempts = 0; // const pollForMatchingBet = async (): Promise => { // try { // const openBets = await fetchOpenBets(solWallet); // const match = openBets.find( // (bet) => // bet.owner_id === lastActiveBet.owner_id && // bet.wager === lastActiveBet.wager && // bet.address !== lastActiveBet.address // to ensure it's a new one // ); // return match ?? null; // } catch (err) { // console.error("Error fetching bets:", err); // return null; // } // }; // const tryJoin = async () => { // while (attempts < maxAttempts) { // const matchingBet = await pollForMatchingBet(); // if (matchingBet) { // try { // setRematchBetAddress(matchingBet.address); // const tx = await joinBet( // solWallet, // user?.id ?? "", // lastActiveBet.id ?? "tetris", // matchingBet.address // ); // console.log("Joined rematch:", tx); // setRematch(false); // return; // } catch (err) { // console.error("Join rematch failed:", err); // setRematchTxError(true); // return; // } finally { // setRematchInProgress(false); // } // } // attempts++; // await new Promise((res) => setTimeout(res, 5000)); // } // // Max attempts reached // setRematchTxError(true); // setRematchInProgress(false); // }; // tryJoin(); // }; useEffect(() => { if (!ready) return; updateBets(); const interval = setInterval(updateBets, 3500); return () => clearInterval(interval); }, [ready]); useEffect(() => { const handleMessage = (event: MessageEvent) => { if (event.origin === window.location.origin && typeof event.data === "string") { try { const message = JSON.parse(event.data); if (message?.type === "gameClose" && typeof message.status === "number") { game_close_signal(message.status); } } catch (error) { console.error("JSON parse error from Unity message:", error); } } }; window.addEventListener("message", handleMessage); return () => window.removeEventListener("message", handleMessage); }, []); return ( <> {myActiveBet && !rematch ? (