import { useState, useEffect } from "react"; import Web3 from "web3"; import { Button } from "./Button"; import { Input } from "./Input"; interface GameListProps { account: string; contract: any; config: Config | null; web3: Web3 | null; setStatus: (status: string) => void; onPlayClick?: (gameId: number) => void; } interface GameInfo { gameId: number; playerA: string; playerB: string; initialBet: string; isActive: boolean; outcome: number; } export default function GameList({ account, contract, config, web3, setStatus, onPlayClick, }: Readonly) { const [games, setGames] = useState([]); const [loading, setLoading] = useState(false); const [newGameBet, setNewGameBet] = useState("0.01"); const [refreshInterval, setRefreshInterval] = useState(null); const [userGameIds, setUserGameIds] = useState>(new Set()); // Fetch all active games const fetchActiveGames = async () => { if (!contract || !web3) return; try { const activeGameIds = await contract.methods.getActiveGameIds().call(); const gameDetails: GameInfo[] = []; for (const gameId of activeGameIds) { const details = await contract.methods.getGameDetails(gameId).call(); gameDetails.push({ gameId: Number(gameId), playerA: details.playerAAddr, playerB: details.playerBAddr, initialBet: web3.utils.fromWei(details.initialBet, "ether"), isActive: details.isActive, outcome: Number(details.outcome), }); } setGames(gameDetails); // Check which games the user is participating in if (account) { const userGames = new Set(); for (const game of gameDetails) { if ( game.playerA.toLowerCase() === account.toLowerCase() || game.playerB.toLowerCase() === account.toLowerCase() ) { userGames.add(game.gameId); } } setUserGameIds(userGames); } } catch (err: any) { console.error("Failed to fetch games:", err.message); } }; // Auto-refresh games every 2 seconds useEffect(() => { fetchActiveGames(); const interval = setInterval(() => { fetchActiveGames(); }, 2000); setRefreshInterval(interval); return () => { if (interval) clearInterval(interval); }; }, [contract, web3, account]); // Join an existing game const handleJoinGame = async (gameId: number, bet: string) => { if (!contract || !web3 || !account) return; setLoading(true); setStatus(""); try { const betWei = web3.utils.toWei(bet || "0.01", "ether"); const tx = contract.methods.register(gameId); const gas = await tx.estimateGas({ from: account, value: betWei }); const result = await (globalThis as any).ethereum.request({ method: "eth_sendTransaction", params: [ { from: account, to: config?.GAME_CONTRACT_ADDRESS, data: tx.encodeABI(), value: web3.utils.numberToHex(betWei), gas: web3.utils.toHex(gas), chainId: web3.utils.toHex(await web3.eth.net.getId()), }, ], }); setStatus("✅ Joined game! Transaction: " + result); await new Promise((resolve) => setTimeout(resolve, 2000)); fetchActiveGames(); } catch (err: any) { setStatus("❌ Failed to join game: " + err.message); console.error(err); } finally { setLoading(false); } }; // Create a new game const handleCreateGame = async () => { if (!contract || !web3 || !account) return; setLoading(true); setStatus(""); try { const betWei = web3.utils.toWei(newGameBet || "0.01", "ether"); const tx = contract.methods.register(0); // 0 means create new game const gas = await tx.estimateGas({ from: account, value: betWei }); const result = await (globalThis as any).ethereum.request({ method: "eth_sendTransaction", params: [ { from: account, to: config?.GAME_CONTRACT_ADDRESS, data: tx.encodeABI(), value: web3.utils.numberToHex(betWei), gas: web3.utils.toHex(gas), chainId: web3.utils.toHex(await web3.eth.net.getId()), }, ], }); setStatus("✅ Created new game! Transaction: " + result); setNewGameBet("0.01"); await new Promise((resolve) => setTimeout(resolve, 2000)); fetchActiveGames(); } catch (err: any) { setStatus("❌ Failed to create game: " + err.message); console.error(err); } finally { setLoading(false); } }; const formatAddress = (addr: string) => { if (!addr || addr === "0x0000000000000000000000000000000000000000") return "-"; return `${addr.slice(0, 6)}...${addr.slice(-4)}`; }; return (
{/* Create New Game Section */}

➕ Create New Game

setNewGameBet(e.target.value)} className="flex-1 min-w-[200px]" />

Enter the bet amount in ETH (e.g., 0.01 for 0.01 ETH). The first player to join with the same or higher bet will play against you.

{/* Active Games List */}

🎮 Available Games ({games.length})

{games.length === 0 ? (

No active games available.

Create a new game to get started!

) : (
{games.map((game) => (
{/* Game ID */}

Game ID

#{game.gameId}

{/* Players Info */}

Players

A: {formatAddress(game.playerA)}

B: {game.playerB === "0x0000000000000000000000000000000000000000" ? "Waiting..." : formatAddress(game.playerB)}

{/* Bet Amount */}

Bet

{game.initialBet} ETH

{/* Join/Play Button */}
{userGameIds.has(game.gameId) ? ( ) : ( )}
))}
)}
{/* Refresh Info */}

🔄 Games refresh automatically every 2 seconds

); }