import { useState, useEffect } from "react"; import Web3 from "web3"; import { Button } from "./Button"; import { GameDetails } from "./GameModal"; import { showSuccessToast, showErrorToast } from "@/app/lib/toast"; interface RevealProps { account: string; contract: any; config: Config | null; web3: Web3 | null; setStatus: (status: string) => void; selectedMove: string | null; secret: string; gameDetails: GameDetails | null; whoAmI: "player1" | "player2" | ""; } type MoveName = "Rock" | "Paper" | "Scissors"; const MOVES: Record = { "1": { name: "Rock", icon: "✊" }, "2": { name: "Paper", icon: "✋" }, "3": { name: "Scissors", icon: "✌️" }, }; const OUTCOMES: Record = { 0: { name: "None", emoji: "❓", color: "gray" }, 1: { name: "You Won!", emoji: "🏆", color: "green" }, 2: { name: "You Lost", emoji: "😢", color: "red" }, 3: { name: "Draw", emoji: "🤝", color: "yellow" }, }; export default function Reveal({ account, contract, config, web3, setStatus, selectedMove, secret, gameDetails, whoAmI, }: Readonly) { const [loading, setLoading] = useState(false); const [selfRevealed, setSelfRevealed] = useState(false); const [opponentRevealed, setOpponentRevealed] = useState(false); const [bothRevealed, setBothRevealed] = useState(false); const [outcome, setOutcome] = useState(0); const clearMove = selectedMove && secret ? `${selectedMove}-${secret}` : ""; // Check game status on mount useEffect(() => { const setStateFromGameDetails = () => { if (!gameDetails) return; const playerARevealed = Number(gameDetails.playerA.move) !== 0; const playerBRevealed = Number(gameDetails.playerB.move) !== 0; setSelfRevealed( (whoAmI === "player1" && playerARevealed) || (whoAmI === "player2" && playerBRevealed) ); setOpponentRevealed( (whoAmI === "player1" && playerBRevealed) || (whoAmI === "player2" && playerARevealed) ); setBothRevealed(playerARevealed && playerBRevealed); if(bothRevealed){ if(Number(gameDetails.outcome) === 1 && whoAmI === "player1") setOutcome(1); else if(Number(gameDetails.outcome) === 2 && whoAmI === "player2") setOutcome(1); else if(Number(gameDetails.outcome) === 1 && whoAmI === "player2") setOutcome(2); else if(Number(gameDetails.outcome) === 2 && whoAmI === "player1") setOutcome(2); else setOutcome(3); } }; setStateFromGameDetails(); }, [gameDetails, contract, account, whoAmI]); const handleReveal = async () => { if (!contract || !web3 || !account || !clearMove) return; setLoading(true); try { const tx = contract.methods.reveal(gameDetails?.returnGameId, clearMove); const gas = await tx.estimateGas({ from: account }); const result = await (globalThis as any).ethereum.request({ method: "eth_sendTransaction", params: [ { from: account, to: config?.GAME_CONTRACT_ADDRESS, data: tx.encodeABI(), gas: web3.utils.toHex(gas), chainId: web3.utils.toHex(await web3.eth.net.getId()), }, ], }); showSuccessToast("Reveal tx sent: " + result); } catch (err: any) { showErrorToast("Reveal failed: " + err.message); } finally { setLoading(false); } }; const handleGetOutcome = async () => { if (!contract || !web3 || !account) return; setLoading(true); try { const tx = contract.methods.getOutcome(gameDetails?.returnGameId); const gas = await tx.estimateGas({ from: account }); const result = await (globalThis as any).ethereum.request({ method: "eth_sendTransaction", params: [ { from: account, to: config?.GAME_CONTRACT_ADDRESS, data: tx.encodeABI(), gas: web3.utils.toHex(gas), chainId: web3.utils.toHex(await web3.eth.net.getId()), }, ], }); showSuccessToast("Claim tx sent: " + result); } catch (err: any) { console.error(err); showErrorToast("Claim failed: " + err.message); } finally { setLoading(false); } }; const outcomeData = OUTCOMES[outcome] || OUTCOMES[0]; return (
{/* Your Move Section - Hidden when both revealed */} {!bothRevealed && (

Your Move

{selectedMove ? (
{MOVES[selectedMove].icon} {MOVES[selectedMove].name}

Clear Move:

{clearMove}
) : (

No move selected yet

)}
)} {/* Game Status Section - Hidden when both revealed */} {!bothRevealed && (

{selfRevealed ? "✅" : "⏳"}

Me

{selfRevealed ? "Revealed" : "Waiting"}

{opponentRevealed ? "✅" : "⏳"}

Opponent

{opponentRevealed ? "Revealed" : "Waiting"}

⏱️

Time Left

{0}

)} {/* Reveal Section - Hidden when both revealed */} {!bothRevealed && (

Reveal Your Move

Submit your clear move and secret to the blockchain. This proves you didn't cheat!

)} {/* Winner Section - Only show if both revealed */} {bothRevealed && (
{/* Moves Comparison */}

Final Moves

{/* Your Move (always on left) */}
{gameDetails && MOVES[String(whoAmI === "player1" ? gameDetails.playerA.move : gameDetails.playerB.move)]?.icon} You {gameDetails && MOVES[String(whoAmI === "player1" ? gameDetails.playerA.move : gameDetails.playerB.move)]?.name}
{/* VS */}
VS
{/* Opponent Move (always on right) */}
{gameDetails && MOVES[String(whoAmI === "player1" ? gameDetails.playerB.move : gameDetails.playerA.move)]?.icon} Opponent {gameDetails && MOVES[String(whoAmI === "player1" ? gameDetails.playerB.move : gameDetails.playerA.move)]?.name}
{/* Outcome Section */}

{outcomeData.emoji}

{outcomeData.name}

{/* Show Claim Coins button only on win or draw and if game is active */} {(outcome === 1 || outcome === 3) && gameDetails?.isActive && ( )}
)}
); }