mirror of
https://github.com/averel10/crypto_clash.git
synced 2026-03-12 19:08:11 +01:00
init contract frontent
This commit is contained in:
53
crypto_clash_frontend/app/clash/Commit.tsx
Normal file
53
crypto_clash_frontend/app/clash/Commit.tsx
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
interface CommitProps {
|
||||||
|
playMove: string;
|
||||||
|
setPlayMove: (v: string) => void;
|
||||||
|
handlePlay: () => void;
|
||||||
|
loading: boolean;
|
||||||
|
account: string;
|
||||||
|
contract: any;
|
||||||
|
bothPlayed: string;
|
||||||
|
handleBothPlayed: () => void;
|
||||||
|
revealTimeLeft: string;
|
||||||
|
handleRevealTimeLeft: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Commit({
|
||||||
|
playMove,
|
||||||
|
setPlayMove,
|
||||||
|
handlePlay,
|
||||||
|
loading,
|
||||||
|
account,
|
||||||
|
contract,
|
||||||
|
bothPlayed,
|
||||||
|
handleBothPlayed,
|
||||||
|
revealTimeLeft,
|
||||||
|
handleRevealTimeLeft,
|
||||||
|
}: Readonly<CommitProps>) {
|
||||||
|
return (
|
||||||
|
<div className="border p-4 rounded-lg">
|
||||||
|
<h2 className="font-semibold mb-2">play(bytes32 encrMove)</h2>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Encrypted Move (bytes32)"
|
||||||
|
value={playMove}
|
||||||
|
onChange={(e) => setPlayMove(e.target.value)}
|
||||||
|
className="border px-2 py-1 mr-2 rounded"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handlePlay}
|
||||||
|
disabled={loading || !account || !contract}
|
||||||
|
className="bg-blue-500 text-white px-4 py-2 rounded"
|
||||||
|
>
|
||||||
|
Play
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="mt-4 space-y-2">
|
||||||
|
<button onClick={handleBothPlayed} className="bg-gray-200 px-2 py-1 rounded">bothPlayed</button>
|
||||||
|
<span className="ml-2 text-xs">{bothPlayed}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleRevealTimeLeft} className="bg-gray-200 px-2 py-1 rounded">revealTimeLeft</button>
|
||||||
|
<span className="ml-2 text-xs">{revealTimeLeft}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
122
crypto_clash_frontend/app/clash/Lobby.tsx
Normal file
122
crypto_clash_frontend/app/clash/Lobby.tsx
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
interface LobbyProps {
|
||||||
|
registerGameId: string;
|
||||||
|
setRegisterGameId: (v: string) => void;
|
||||||
|
registerBet: string;
|
||||||
|
setRegisterBet: (v: string) => void;
|
||||||
|
handleRegister: () => void;
|
||||||
|
loading: boolean;
|
||||||
|
account: string;
|
||||||
|
contract: any;
|
||||||
|
betMin: string;
|
||||||
|
handleGetBetMin: () => void;
|
||||||
|
activeGameIds: string;
|
||||||
|
handleGetActiveGameIds: () => void;
|
||||||
|
contractBalance: string;
|
||||||
|
handleGetContractBalance: () => void;
|
||||||
|
gameDetailsId: string;
|
||||||
|
setGameDetailsId: (v: string) => void;
|
||||||
|
gameDetails: any;
|
||||||
|
handleGetGameDetails: () => void;
|
||||||
|
myActiveGameId: string;
|
||||||
|
handleGetMyActiveGameId: () => void;
|
||||||
|
pastGameIndex: string;
|
||||||
|
setPastGameIndex: (v: string) => void;
|
||||||
|
pastGame: any;
|
||||||
|
handleGetPastGame: () => void;
|
||||||
|
pastGamesCount: string;
|
||||||
|
handleGetPastGamesCount: () => void;
|
||||||
|
whoAmI: string;
|
||||||
|
handleWhoAmI: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Lobby({
|
||||||
|
registerGameId,
|
||||||
|
setRegisterGameId,
|
||||||
|
registerBet,
|
||||||
|
setRegisterBet,
|
||||||
|
handleRegister,
|
||||||
|
loading,
|
||||||
|
account,
|
||||||
|
contract,
|
||||||
|
betMin,
|
||||||
|
handleGetBetMin,
|
||||||
|
activeGameIds,
|
||||||
|
handleGetActiveGameIds,
|
||||||
|
contractBalance,
|
||||||
|
handleGetContractBalance,
|
||||||
|
gameDetailsId,
|
||||||
|
setGameDetailsId,
|
||||||
|
gameDetails,
|
||||||
|
handleGetGameDetails,
|
||||||
|
myActiveGameId,
|
||||||
|
handleGetMyActiveGameId,
|
||||||
|
pastGameIndex,
|
||||||
|
setPastGameIndex,
|
||||||
|
pastGame,
|
||||||
|
handleGetPastGame,
|
||||||
|
pastGamesCount,
|
||||||
|
handleGetPastGamesCount,
|
||||||
|
whoAmI,
|
||||||
|
handleWhoAmI,
|
||||||
|
}: Readonly<LobbyProps>) {
|
||||||
|
return (
|
||||||
|
<div className="border p-4 rounded-lg">
|
||||||
|
<h2 className="font-semibold mb-2">register(uint gameId) (payable)</h2>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Game ID (0 = auto)"
|
||||||
|
value={registerGameId}
|
||||||
|
onChange={(e) => setRegisterGameId(e.target.value)}
|
||||||
|
className="border px-2 py-1 mr-2 rounded"
|
||||||
|
/>
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
min="0.01"
|
||||||
|
step="0.01"
|
||||||
|
placeholder="Bet in ETH (default 0.01)"
|
||||||
|
value={registerBet}
|
||||||
|
onChange={(e) => setRegisterBet(e.target.value)}
|
||||||
|
className="border px-2 py-1 mr-2 rounded"
|
||||||
|
/>
|
||||||
|
<div className="text-xs text-slate-500 mt-1">
|
||||||
|
Enter amount in ETH (e.g., 0.01 for 0.01 ETH). Entering 1 means 1 full
|
||||||
|
ETH.
|
||||||
|
</div>
|
||||||
|
<button
|
||||||
|
onClick={handleRegister}
|
||||||
|
disabled={loading || !account || !contract}
|
||||||
|
className="bg-blue-500 text-white px-4 py-2 rounded"
|
||||||
|
>
|
||||||
|
Register
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="mt-4 space-y-2">
|
||||||
|
<button onClick={handleGetBetMin} className="bg-gray-200 px-2 py-1 rounded">BET_MIN</button>
|
||||||
|
<span className="ml-2 text-xs">{betMin}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleGetActiveGameIds} className="bg-gray-200 px-2 py-1 rounded">getActiveGameIds</button>
|
||||||
|
<span className="ml-2 text-xs">{activeGameIds}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleGetContractBalance} className="bg-gray-200 px-2 py-1 rounded">getContractBalance</button>
|
||||||
|
<span className="ml-2 text-xs">{contractBalance}</span>
|
||||||
|
<br />
|
||||||
|
<input type="text" placeholder="Game ID" value={gameDetailsId} onChange={e => setGameDetailsId(e.target.value)} className="border px-2 py-1 mr-2 rounded" />
|
||||||
|
<button onClick={handleGetGameDetails} className="bg-gray-200 px-2 py-1 rounded">getGameDetails</button>
|
||||||
|
<span className="ml-2 text-xs">{gameDetails && <pre className="inline whitespace-pre-wrap">{JSON.stringify(gameDetails, null, 2)}</pre>}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleGetMyActiveGameId} className="bg-gray-200 px-2 py-1 rounded">getMyActiveGameId</button>
|
||||||
|
<span className="ml-2 text-xs">{myActiveGameId}</span>
|
||||||
|
<br />
|
||||||
|
<input type="text" placeholder="Past Game Index" value={pastGameIndex} onChange={e => setPastGameIndex(e.target.value)} className="border px-2 py-1 mr-2 rounded" />
|
||||||
|
<button onClick={handleGetPastGame} className="bg-gray-200 px-2 py-1 rounded">getPastGame</button>
|
||||||
|
<span className="ml-2 text-xs">{pastGame && <pre className="inline whitespace-pre-wrap">{JSON.stringify(pastGame, null, 2)}</pre>}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleGetPastGamesCount} className="bg-gray-200 px-2 py-1 rounded">getPastGamesCount</button>
|
||||||
|
<span className="ml-2 text-xs">{pastGamesCount}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleWhoAmI} className="bg-gray-200 px-2 py-1 rounded">whoAmI</button>
|
||||||
|
<span className="ml-2 text-xs">{whoAmI}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
67
crypto_clash_frontend/app/clash/Reveal.tsx
Normal file
67
crypto_clash_frontend/app/clash/Reveal.tsx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
interface RevealProps {
|
||||||
|
revealMove: string;
|
||||||
|
setRevealMove: (v: string) => void;
|
||||||
|
handleReveal: () => void;
|
||||||
|
loading: boolean;
|
||||||
|
account: string;
|
||||||
|
contract: any;
|
||||||
|
bothRevealed: string;
|
||||||
|
handleBothRevealed: () => void;
|
||||||
|
playerARevealed: string;
|
||||||
|
handlePlayerARevealed: () => void;
|
||||||
|
playerBRevealed: string;
|
||||||
|
handlePlayerBRevealed: () => void;
|
||||||
|
revealTimeLeft: string;
|
||||||
|
handleRevealTimeLeft: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Reveal({
|
||||||
|
revealMove,
|
||||||
|
setRevealMove,
|
||||||
|
handleReveal,
|
||||||
|
loading,
|
||||||
|
account,
|
||||||
|
contract,
|
||||||
|
bothRevealed,
|
||||||
|
handleBothRevealed,
|
||||||
|
playerARevealed,
|
||||||
|
handlePlayerARevealed,
|
||||||
|
playerBRevealed,
|
||||||
|
handlePlayerBRevealed,
|
||||||
|
revealTimeLeft,
|
||||||
|
handleRevealTimeLeft,
|
||||||
|
}: Readonly<RevealProps>) {
|
||||||
|
return (
|
||||||
|
<div className="border p-4 rounded-lg">
|
||||||
|
<h2 className="font-semibold mb-2">reveal(string clearMove)</h2>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="Clear Move (e.g. 1-password)"
|
||||||
|
value={revealMove}
|
||||||
|
onChange={(e) => setRevealMove(e.target.value)}
|
||||||
|
className="border px-2 py-1 mr-2 rounded"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={handleReveal}
|
||||||
|
disabled={loading || !account || !contract}
|
||||||
|
className="bg-blue-500 text-white px-4 py-2 rounded"
|
||||||
|
>
|
||||||
|
Reveal
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<div className="mt-4 space-y-2">
|
||||||
|
<button onClick={handleBothRevealed} className="bg-gray-200 px-2 py-1 rounded">bothRevealed</button>
|
||||||
|
<span className="ml-2 text-xs">{bothRevealed}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handlePlayerARevealed} className="bg-gray-200 px-2 py-1 rounded">playerARevealed</button>
|
||||||
|
<span className="ml-2 text-xs">{playerARevealed}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handlePlayerBRevealed} className="bg-gray-200 px-2 py-1 rounded">playerBRevealed</button>
|
||||||
|
<span className="ml-2 text-xs">{playerBRevealed}</span>
|
||||||
|
<br />
|
||||||
|
<button onClick={handleRevealTimeLeft} className="bg-gray-200 px-2 py-1 rounded">revealTimeLeft</button>
|
||||||
|
<span className="ml-2 text-xs">{revealTimeLeft}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,11 +1,520 @@
|
|||||||
"use client";
|
"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() {
|
export default function Clash() {
|
||||||
|
const [config, setConfig] = useState<Config | null>(null);
|
||||||
|
const [web3, setWeb3] = useState<Web3 | null>(null);
|
||||||
|
const [contract, setContract] = useState<any>(null);
|
||||||
|
const [account, setAccount] = useState<string>("");
|
||||||
|
const [status, setStatus] = useState<string>("");
|
||||||
|
const [loading, setLoading] = useState(false);
|
||||||
|
|
||||||
|
// Inputs for contract functions
|
||||||
|
const [phase, setPhase] = useState<"lobby" | "commit" | "reveal">("lobby");
|
||||||
|
|
||||||
|
const [registerGameId, setRegisterGameId] = useState<string>("0");
|
||||||
|
const [registerBet, setRegisterBet] = useState<string>("");
|
||||||
|
const [playMove, setPlayMove] = useState<string>("");
|
||||||
|
const [revealMove, setRevealMove] = useState<string>("");
|
||||||
|
// State for read-only contract calls
|
||||||
|
const [betMin, setBetMin] = useState<string>("");
|
||||||
|
const [activeGameIds, setActiveGameIds] = useState<string>("");
|
||||||
|
const [contractBalance, setContractBalance] = useState<string>("");
|
||||||
|
const [gameDetailsId, setGameDetailsId] = useState<string>("");
|
||||||
|
const [gameDetails, setGameDetails] = useState<any>(null);
|
||||||
|
const [myActiveGameId, setMyActiveGameId] = useState<string>("");
|
||||||
|
const [pastGameIndex, setPastGameIndex] = useState<string>("");
|
||||||
|
const [pastGame, setPastGame] = useState<any>(null);
|
||||||
|
const [pastGamesCount, setPastGamesCount] = useState<string>("");
|
||||||
|
const [whoAmI, setWhoAmI] = useState<string>("");
|
||||||
|
const [bothPlayed, setBothPlayed] = useState<string>("");
|
||||||
|
const [revealTimeLeft, setRevealTimeLeft] = useState<string>("");
|
||||||
|
const [bothRevealed, setBothRevealed] = useState<string>("");
|
||||||
|
const [playerARevealed, setPlayerARevealed] = useState<string>("");
|
||||||
|
const [playerBRevealed, setPlayerBRevealed] = useState<string>("");
|
||||||
|
// Reveal phase read-only handlers
|
||||||
|
const handleBothRevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.bothRevealed().call();
|
||||||
|
setBothRevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch bothRevealed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePlayerARevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.playerARevealed().call();
|
||||||
|
setPlayerARevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch playerARevealed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePlayerBRevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.playerBRevealed().call();
|
||||||
|
setPlayerBRevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch playerBRevealed: " + err.message);
|
||||||
|
const [bothRevealed, setBothRevealed] = useState<string>("");
|
||||||
|
const [playerARevealed, setPlayerARevealed] = useState<string>("");
|
||||||
|
const [playerBRevealed, setPlayerBRevealed] = useState<string>("");
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// Commit phase read-only handlers
|
||||||
|
const handleBothPlayed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.bothPlayed().call();
|
||||||
|
setBothPlayed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch bothPlayed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handleRevealTimeLeft = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.revealTimeLeft().call();
|
||||||
|
setRevealTimeLeft(res.toString());
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch revealTimeLeft: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
// 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 () => {
|
||||||
|
// Reveal phase read-only handlers
|
||||||
|
const handleBothRevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.bothRevealed().call();
|
||||||
|
setBothRevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch bothRevealed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePlayerARevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.playerARevealed().call();
|
||||||
|
setPlayerARevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch playerARevealed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const handlePlayerBRevealed = async () => {
|
||||||
|
if (!contract) return;
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const res = await contract.methods.playerBRevealed().call();
|
||||||
|
setPlayerBRevealed(res ? "true" : "false");
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Failed to fetch playerBRevealed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handlePlay = async () => {
|
||||||
|
if (!contract || !web3 || !account) return;
|
||||||
|
setLoading(true);
|
||||||
|
setStatus("");
|
||||||
|
try {
|
||||||
|
// playMove should be a hex string (bytes32)
|
||||||
|
const tx = contract.methods.play(playMove);
|
||||||
|
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()),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
setStatus("Play tx sent: " + result);
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Play failed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReveal = async () => {
|
||||||
|
if (!contract || !web3 || !account) return;
|
||||||
|
setLoading(true);
|
||||||
|
setStatus("");
|
||||||
|
try {
|
||||||
|
const tx = contract.methods.reveal(revealMove);
|
||||||
|
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()),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
setStatus("Reveal tx sent: " + result);
|
||||||
|
} catch (err: any) {
|
||||||
|
setStatus("Reveal failed: " + err.message);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div className="flex min-h-screen items-center justify-center bg-gradient-to-br from-blue-50 to-indigo-100 dark:from-slate-900 dark:to-slate-800 font-sans">
|
||||||
<h1>Clash Page</h1>
|
<main className="w-full max-w-3xl mx-auto py-12 px-6">
|
||||||
<p>This is the Clash page content.</p>
|
<div className="bg-white dark:bg-slate-800 rounded-lg shadow-lg p-8">
|
||||||
|
<h1 className="text-4xl font-bold text-center mb-2 text-slate-900 dark:text-white">
|
||||||
|
Crypto Clash
|
||||||
|
</h1>
|
||||||
|
<p className="text-center text-slate-600 dark:text-slate-300 mb-8">
|
||||||
|
{phase === "lobby" && "Register for a game to start."}
|
||||||
|
{phase === "commit" && "Commit your move."}
|
||||||
|
{phase === "reveal" && "Reveal your move."}
|
||||||
|
</p>
|
||||||
|
<div className="mb-8 p-4 bg-slate-100 dark:bg-slate-700 rounded-lg">
|
||||||
|
<p className="text-sm text-slate-600 dark:text-slate-300">
|
||||||
|
<span className="font-semibold">Connected Account:</span>{" "}
|
||||||
|
{account
|
||||||
|
? `${account.slice(0, 6)}...${account.slice(-4)}`
|
||||||
|
: "Not connected"}
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-slate-600 dark:text-slate-300 mt-2">
|
||||||
|
<span className="font-semibold">Game Contract Address:</span>{" "}
|
||||||
|
{config?.GAME_CONTRACT_ADDRESS}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="flex justify-center mb-6 space-x-4">
|
||||||
|
<button
|
||||||
|
onClick={() => setPhase("lobby")}
|
||||||
|
className={`px-4 py-2 rounded ${
|
||||||
|
phase === "lobby"
|
||||||
|
? "bg-blue-600 text-white"
|
||||||
|
: "bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Lobby
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setPhase("commit")}
|
||||||
|
className={`px-4 py-2 rounded ${
|
||||||
|
phase === "commit"
|
||||||
|
? "bg-blue-600 text-white"
|
||||||
|
: "bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Commit
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={() => setPhase("reveal")}
|
||||||
|
className={`px-4 py-2 rounded ${
|
||||||
|
phase === "reveal"
|
||||||
|
? "bg-blue-600 text-white"
|
||||||
|
: "bg-gray-200 dark:bg-gray-700 text-gray-800 dark:text-gray-200"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
Reveal
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-6">
|
||||||
|
{phase === "lobby" && (
|
||||||
|
<Lobby
|
||||||
|
registerGameId={registerGameId}
|
||||||
|
setRegisterGameId={setRegisterGameId}
|
||||||
|
registerBet={registerBet}
|
||||||
|
setRegisterBet={setRegisterBet}
|
||||||
|
handleRegister={handleRegister}
|
||||||
|
loading={loading}
|
||||||
|
account={account}
|
||||||
|
contract={contract}
|
||||||
|
betMin={betMin}
|
||||||
|
handleGetBetMin={handleGetBetMin}
|
||||||
|
activeGameIds={activeGameIds}
|
||||||
|
handleGetActiveGameIds={handleGetActiveGameIds}
|
||||||
|
contractBalance={contractBalance}
|
||||||
|
handleGetContractBalance={handleGetContractBalance}
|
||||||
|
gameDetailsId={gameDetailsId}
|
||||||
|
setGameDetailsId={setGameDetailsId}
|
||||||
|
gameDetails={gameDetails}
|
||||||
|
handleGetGameDetails={handleGetGameDetails}
|
||||||
|
myActiveGameId={myActiveGameId}
|
||||||
|
handleGetMyActiveGameId={handleGetMyActiveGameId}
|
||||||
|
pastGameIndex={pastGameIndex}
|
||||||
|
setPastGameIndex={setPastGameIndex}
|
||||||
|
pastGame={pastGame}
|
||||||
|
handleGetPastGame={handleGetPastGame}
|
||||||
|
pastGamesCount={pastGamesCount}
|
||||||
|
handleGetPastGamesCount={handleGetPastGamesCount}
|
||||||
|
whoAmI={whoAmI}
|
||||||
|
handleWhoAmI={handleWhoAmI}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{phase === "commit" && (
|
||||||
|
<Commit
|
||||||
|
playMove={playMove}
|
||||||
|
setPlayMove={setPlayMove}
|
||||||
|
handlePlay={handlePlay}
|
||||||
|
loading={loading}
|
||||||
|
account={account}
|
||||||
|
contract={contract}
|
||||||
|
bothPlayed={bothPlayed}
|
||||||
|
handleBothPlayed={handleBothPlayed}
|
||||||
|
revealTimeLeft={revealTimeLeft}
|
||||||
|
handleRevealTimeLeft={handleRevealTimeLeft}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{phase === "reveal" && (
|
||||||
|
<Reveal
|
||||||
|
revealMove={revealMove}
|
||||||
|
setRevealMove={setRevealMove}
|
||||||
|
handleReveal={handleReveal}
|
||||||
|
loading={loading}
|
||||||
|
account={account}
|
||||||
|
contract={contract}
|
||||||
|
bothRevealed={bothRevealed}
|
||||||
|
handleBothRevealed={handleBothRevealed}
|
||||||
|
playerARevealed={playerARevealed}
|
||||||
|
handlePlayerARevealed={handlePlayerARevealed}
|
||||||
|
playerBRevealed={playerBRevealed}
|
||||||
|
handlePlayerBRevealed={handlePlayerBRevealed}
|
||||||
|
revealTimeLeft={revealTimeLeft}
|
||||||
|
handleRevealTimeLeft={handleRevealTimeLeft}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
{status && (
|
||||||
|
<div
|
||||||
|
className={`mt-6 p-4 rounded-lg ${
|
||||||
|
status.includes("tx sent")
|
||||||
|
? "bg-green-50 dark:bg-green-900 text-green-800 dark:text-green-200"
|
||||||
|
: "bg-red-50 dark:bg-red-900 text-red-800 dark:text-red-200"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
<p className="text-sm break-words">{status}</p>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
<div className="mt-8 p-4 bg-yellow-50 dark:bg-yellow-900 rounded-lg text-sm text-yellow-800 dark:text-yellow-200">
|
||||||
|
<p className="font-semibold mb-2">ℹ️ Note:</p>
|
||||||
|
<ul className="list-disc list-inside space-y-1">
|
||||||
|
<li>
|
||||||
|
MetaMask or a compatible Web3 wallet is required for write
|
||||||
|
operations
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Use bytes32 for encrypted move (see contract docs for details)
|
||||||
|
</li>
|
||||||
|
<li>ETH values are in Ether (not Wei)</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
60
crypto_clash_frontend/package-lock.json
generated
60
crypto_clash_frontend/package-lock.json
generated
@@ -1544,6 +1544,66 @@
|
|||||||
"node": ">=14.0.0"
|
"node": ">=14.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/wasi-threads": "1.1.0",
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@emnapi/core": "^1.5.0",
|
||||||
|
"@emnapi/runtime": "^1.5.0",
|
||||||
|
"@tybys/wasm-util": "^0.10.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": {
|
||||||
|
"version": "0.10.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"optional": true,
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": "^2.4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": {
|
||||||
|
"version": "2.8.1",
|
||||||
|
"dev": true,
|
||||||
|
"inBundle": true,
|
||||||
|
"license": "0BSD",
|
||||||
|
"optional": true
|
||||||
|
},
|
||||||
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
"node_modules/@tailwindcss/oxide-win32-arm64-msvc": {
|
||||||
"version": "4.1.17",
|
"version": "4.1.17",
|
||||||
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz",
|
"resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.17.tgz",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"API_URL": "https://rpc.hasrv.averel10.app/",
|
"API_URL": "https://rpc.hasrv.averel10.app/",
|
||||||
"CONTRACT_ADDRESS": "0xC3D2A1471A5e19ce586D4D3cB398Ce560efAF6Ca",
|
"CONTRACT_ADDRESS": "0x8B7746B922a80d9B29cA939fD90577932527112C",
|
||||||
"ABI": [
|
"ABI": [
|
||||||
{
|
{
|
||||||
"inputs": [
|
"inputs": [
|
||||||
@@ -58,5 +58,325 @@
|
|||||||
"stateMutability": "nonpayable",
|
"stateMutability": "nonpayable",
|
||||||
"type": "function"
|
"type": "function"
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"GAME_CONTRACT_ADDRESS": "0x9230eBBB05c3e953a5F135F032b352c6F0B6E164",
|
||||||
|
"GAME_ABI": [
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "BET_MIN",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "REVEAL_TIMEOUT",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "bothPlayed",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "bothRevealed",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getActiveGameIds",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256[]",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256[]"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getContractBalance",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "gameId",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getGameDetails",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "playerAAddr",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "playerBAddr",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "initialBet",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "enum Game.Outcomes",
|
||||||
|
"name": "outcome",
|
||||||
|
"type": "uint8"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "isActive",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getLastWinner",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "enum Game.Outcomes",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getMyActiveGameId",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getOutcome",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "enum Game.Outcomes",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "index",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "getPastGame",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "playerAAddr",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "address",
|
||||||
|
"name": "playerBAddr",
|
||||||
|
"type": "address"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "initialBet",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "enum Game.Outcomes",
|
||||||
|
"name": "outcome",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "getPastGamesCount",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bytes32",
|
||||||
|
"name": "encrMove",
|
||||||
|
"type": "bytes32"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "play",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "playerARevealed",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "playerBRevealed",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "bool",
|
||||||
|
"name": "",
|
||||||
|
"type": "bool"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "gameId",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "register",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "playerId",
|
||||||
|
"type": "uint256"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "returnGameId",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "payable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [
|
||||||
|
{
|
||||||
|
"internalType": "string",
|
||||||
|
"name": "clearMove",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"name": "reveal",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "enum Game.Moves",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint8"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "nonpayable",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "revealTimeLeft",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "int256",
|
||||||
|
"name": "",
|
||||||
|
"type": "int256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"inputs": [],
|
||||||
|
"name": "whoAmI",
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"internalType": "uint256",
|
||||||
|
"name": "",
|
||||||
|
"type": "uint256"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"stateMutability": "view",
|
||||||
|
"type": "function"
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user