"use client"; import { useEffect, useState } from "react"; import Web3 from "web3"; import Lobby from "./Lobby"; import Commit from "./Commit"; import Reveal from "./Reveal"; export default function Clash() { const [config, setConfig] = useState(null); const [web3, setWeb3] = useState(null); const [contract, setContract] = useState(null); const [account, setAccount] = useState(""); const [status, setStatus] = useState(""); const [loading, setLoading] = useState(false); // Inputs for contract functions const [phase, setPhase] = useState<"lobby" | "commit" | "reveal">("lobby"); const [registerGameId, setRegisterGameId] = useState("0"); const [registerBet, setRegisterBet] = useState(""); // State for read-only contract calls const [betMin, setBetMin] = useState(""); const [activeGameIds, setActiveGameIds] = useState(""); const [contractBalance, setContractBalance] = useState(""); const [gameDetailsId, setGameDetailsId] = useState(""); const [gameDetails, setGameDetails] = useState(null); const [myActiveGameId, setMyActiveGameId] = useState(""); const [pastGameIndex, setPastGameIndex] = useState(""); const [pastGame, setPastGame] = useState(null); const [pastGamesCount, setPastGamesCount] = useState(""); const [whoAmI, setWhoAmI] = useState(""); // Read-only contract function handlers const handleGetBetMin = async () => { if (!contract || !web3) return; setLoading(true); try { const res = await contract.methods.BET_MIN().call(); setBetMin(web3.utils.fromWei(res, "ether") + " ETH"); } catch (err: any) { setStatus("Failed to fetch BET_MIN: " + err.message); } finally { setLoading(false); } }; const handleGetActiveGameIds = async () => { if (!contract) return; setLoading(true); try { const res = await contract.methods.getActiveGameIds().call(); setActiveGameIds(res.join(", ")); } catch (err: any) { setStatus("Failed to fetch active game IDs: " + err.message); } finally { setLoading(false); } }; const handleGetContractBalance = async () => { if (!contract || !web3) return; setLoading(true); try { const res = await contract.methods.getContractBalance().call(); setContractBalance(web3.utils.fromWei(res, "ether") + " ETH"); } catch (err: any) { setStatus("Failed to fetch contract balance: " + err.message); } finally { setLoading(false); } }; const handleGetGameDetails = async () => { if (!contract) return; setLoading(true); try { const res = await contract.methods .getGameDetails(Number(gameDetailsId)) .call(); setGameDetails(res); } catch (err: any) { setStatus("Failed to fetch game details: " + err.message); } finally { setLoading(false); } }; const handleGetMyActiveGameId = async () => { if (!contract || !account) return; setLoading(true); try { const res = await contract.methods .getMyActiveGameId() .call({ from: account }); setMyActiveGameId(res.toString()); } catch (err: any) { setStatus("Failed to fetch my active game ID: " + err.message); } finally { setLoading(false); } }; const handleGetPastGame = async () => { if (!contract) return; setLoading(true); try { const res = await contract.methods .getPastGame(Number(pastGameIndex)) .call(); setPastGame(res); } catch (err: any) { setStatus("Failed to fetch past game: " + err.message); } finally { setLoading(false); } }; const handleGetPastGamesCount = async () => { if (!contract) return; setLoading(true); try { const res = await contract.methods.getPastGamesCount().call(); setPastGamesCount(res.toString()); } catch (err: any) { setStatus("Failed to fetch past games count: " + err.message); } finally { setLoading(false); } }; const handleWhoAmI = async () => { if (!contract || !account) return; setLoading(true); try { const res = await contract.methods.whoAmI().call({ from: account }); setWhoAmI(res.toString()); } catch (err: any) { setStatus("Failed to fetch whoAmI: " + err.message); } finally { setLoading(false); } }; // (Removed unused inputs and state) // Load config and contract useEffect(() => { const loadConfig = async () => { try { const response = await fetch("/crypto_clash/config.json"); const data = await response.json(); setConfig(data); const web3Instance = new Web3(data.API_URL); setWeb3(web3Instance); const contractInstance = new web3Instance.eth.Contract( data.GAME_ABI, data.GAME_CONTRACT_ADDRESS ); setContract(contractInstance); // Get account if (globalThis.window !== undefined && (globalThis as any).ethereum) { try { const accounts = await (globalThis as any).ethereum.request({ method: "eth_requestAccounts", }); setAccount(accounts[0]); } catch (err: any) { setStatus( "MetaMask not available or user denied access: " + err.message ); } } } catch (err: any) { setStatus("Failed to load config: " + err.message); } }; loadConfig(); }, []); // (Removed unused helpers) // Contract function handlers const handleRegister = async () => { if (!contract || !web3 || !account) return; setLoading(true); setStatus(""); try { console.log(registerBet) const bet = web3.utils.toWei(registerBet || "0.01", "ether"); console.log(bet) console.log(web3.utils.toHex(bet)) const tx = contract.methods.register(Number(registerGameId || 0)); const gas = await tx.estimateGas({ from: account, value: bet }); 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(bet), gas: web3.utils.toHex(gas), chainId: web3.utils.toHex(await web3.eth.net.getId()), }, ], }); setStatus("Register tx sent: " + result); } catch (err: any) { setStatus("Register failed: " + err.message); } finally { setLoading(false); } }; return (

Crypto Clash

{phase === "lobby" && "Register for a game to start."} {phase === "commit" && "Commit your move."} {phase === "reveal" && "Reveal your move."}

Connected Account:{" "} {account ? `${account.slice(0, 6)}...${account.slice(-4)}` : "Not connected"}

Game Contract Address:{" "} {config?.GAME_CONTRACT_ADDRESS}

{phase === "lobby" && ( )} {phase === "commit" && ( )} {phase === "reveal" && ( )}
{status && (

{status}

)}

ℹ️ Note:

  • MetaMask or a compatible Web3 wallet is required for write operations
  • Use bytes32 for encrypted move (see contract docs for details)
  • ETH values are in Ether (not Wei)
); }