diff --git a/packages/nextjs/pages/index.tsx b/packages/nextjs/pages/index.tsx
index 80fda15..141cfce 100644
--- a/packages/nextjs/pages/index.tsx
+++ b/packages/nextjs/pages/index.tsx
@@ -1,11 +1,8 @@
import { useEffect, useState } from "react";
-// import Link from "next/link";
-import { NewGameProps } from "../types/TicTacToeTypes";
+import { GameAcceptedProps, GameCreatedProps, GameFinishedProps, MoveMadeProps } from "../types/TicTacToeTypes";
import { Card, CardBody, Flex, Heading } from "@chakra-ui/react";
import { ethers } from "ethers";
import type { NextPage } from "next";
-// import { parseEther } from "viem";
-// import { BugAntIcon, MagnifyingGlassIcon } from "@heroicons/react/24/outline";
import { MetaHeader } from "~~/components/MetaHeader";
import { Address } from "~~/components/scaffold-eth";
import CreateChallengeBox from "~~/components/tictactoe/CreateChallengeBox";
@@ -13,7 +10,10 @@ import CreateChallengeBox from "~~/components/tictactoe/CreateChallengeBox";
import { useScaffoldEventHistory, useScaffoldEventSubscriber } from "~~/hooks/scaffold-eth";
const Home: NextPage = () => {
- const [gameHistory, setGameHistory] = useState([]);
+ const [gameHistory, setGameHistory] = useState([]);
+ const [gameAcceptedHistory, setGameAcceptedHistory] = useState([]);
+ const [moveMadeHistory, setMoveMadeHistory] = useState([]);
+ const [gameFinishedHistory, setGameFinishedHistory] = useState([]);
// Event history hooks
const { data: GameCreatedHistory } = useScaffoldEventHistory({
@@ -23,6 +23,27 @@ const Home: NextPage = () => {
blockData: false,
});
+ const { data: GameAcceptedHistory } = useScaffoldEventHistory({
+ contractName: "TicTacToe",
+ eventName: "GameAccepted",
+ fromBlock: BigInt(process.env.NEXT_PUBLIC_DEPLOY_BLOCK || "0"),
+ blockData: false,
+ });
+
+ const { data: MoveMadeHistory } = useScaffoldEventHistory({
+ contractName: "TicTacToe",
+ eventName: "MoveMade",
+ fromBlock: BigInt(process.env.NEXT_PUBLIC_DEPLOY_BLOCK || "0"),
+ blockData: false,
+ });
+
+ const { data: GameFinishedHistory } = useScaffoldEventHistory({
+ contractName: "TicTacToe",
+ eventName: "GameFinished",
+ fromBlock: BigInt(process.env.NEXT_PUBLIC_DEPLOY_BLOCK || "0"),
+ blockData: false,
+ });
+
// useEffect for dynamic updating? (not sure if needed)
useEffect(() => {
const mappedHistory = GameCreatedHistory?.map(event => ({
@@ -30,23 +51,105 @@ const Home: NextPage = () => {
player1: event.args[1],
player2: event.args[2],
bet: parseInt(event.args[3].toString()),
- })) as NewGameProps[];
+ })) as GameCreatedProps[];
setGameHistory(mappedHistory);
}, [GameCreatedHistory]);
+ useEffect(() => {
+ const mappedHistory = GameAcceptedHistory?.map(event => ({
+ gameId: parseInt(event.args[0].toString()),
+ player1: event.args[1],
+ player2: event.args[2],
+ })) as GameAcceptedProps[];
+ setGameAcceptedHistory(mappedHistory);
+ }, [GameAcceptedHistory]);
+
+ useEffect(() => {
+ const mappedHistory = MoveMadeHistory?.map(event => ({
+ gameId: parseInt(event.args[0].toString()),
+ player: event.args[1],
+ position: parseInt(event.args[2].toString()),
+ })) as MoveMadeProps[];
+ setMoveMadeHistory(mappedHistory);
+ }, [MoveMadeHistory]);
+
+ useEffect(() => {
+ const mappedHistory = GameFinishedHistory?.map(event => ({
+ gameId: parseInt(event.args[0].toString()),
+ winner: event.args[1],
+ state: parseInt(event.args[2].toString()),
+ })) as GameFinishedProps[];
+ setGameFinishedHistory(mappedHistory);
+ }, [GameFinishedHistory]);
+
// Event subscription hooks
useScaffoldEventSubscriber({
contractName: "TicTacToe",
eventName: "GameCreated",
listener: (logs: any[]) => {
setGameHistory(indexedHistory => {
- const newGameCreated: NewGameProps = {
+ const newGameCreated: GameCreatedProps = {
gameId: parseInt(logs[0].args[0].toString()),
player1: logs[0].args[1],
player2: logs[0].args[2],
bet: parseInt(logs[0].args[3].toString()),
};
- return [newGameCreated, ...indexedHistory];
+
+ // Check if the game with the same gameId already exists
+ const existingGame = indexedHistory.find(game => game.gameId === newGameCreated.gameId);
+
+ // If it doesn't exist, add the new game to the history
+ if (!existingGame) {
+ return [newGameCreated, ...indexedHistory];
+ }
+
+ // If it exists, return the existing history without adding a duplicate
+ return indexedHistory;
+ });
+ },
+ });
+
+ useScaffoldEventSubscriber({
+ contractName: "TicTacToe",
+ eventName: "GameAccepted",
+ listener: (logs: any[]) => {
+ setGameAcceptedHistory(indexedHistory => {
+ const newGameAccepted: GameAcceptedProps = {
+ gameId: parseInt(logs[0].args[0].toString()),
+ player1: logs[0].args[1],
+ player2: logs[0].args[2],
+ };
+ return [newGameAccepted, ...indexedHistory];
+ });
+ },
+ });
+
+ useScaffoldEventSubscriber({
+ contractName: "TicTacToe",
+ eventName: "MoveMade",
+ listener: (logs: any[]) => {
+ setMoveMadeHistory(indexedHistory => {
+ const newMoveMade: MoveMadeProps = {
+ gameId: parseInt(logs[0].args[0].toString()),
+ player: logs[0].args[1],
+ position: parseInt(logs[0].args[2].toString()),
+ };
+ return [newMoveMade, ...indexedHistory];
+ });
+ },
+ });
+
+ useScaffoldEventSubscriber({
+ contractName: "TicTacToe",
+ eventName: "GameFinished",
+ listener: (logs: any[]) => {
+ setGameFinishedHistory(indexedHistory => {
+ const newGameFinished: GameFinishedProps = {
+ gameId: parseInt(logs[0].args[0].toString()),
+ winner: logs[0].args[1],
+ state: parseInt(logs[0].args[2].toString()),
+ };
+ return [newGameFinished, ...indexedHistory];
});
},
});
@@ -94,21 +197,34 @@ const Home: NextPage = () => {
⭕ See your active challenges! ❌
- {gameCards?.map(({ gameId, player1, player2, bet }) => (
- <>
- GameId: {gameId}
-
-
- Player 1:
-
-
- Player 2:
-
- Bet: {parseFloat(ethers.formatEther(bet.toString())).toFixed(4)} ETH
-
- ------------------------
- >
- ))}
+ {gameCards?.map(({ gameId, player1, player2, bet }) => {
+ const isGameAccepted = gameAcceptedHistory.some(acceptedGame => acceptedGame.gameId === gameId);
+ const movesMade = moveMadeHistory.filter(move => move.gameId === gameId).length;
+ const isGameFinished = gameFinishedHistory.some(finishedGame => finishedGame.gameId === gameId);
+
+ return (
+
+
GameId: {gameId}
+
+
+ Player 1:
+
+
+ Player 2:
+
+
+
+ Bet: {parseFloat(ethers.formatEther(bet.toString())).toFixed(4)} ETH
+ Is game accepted?: {isGameAccepted ? "Yes" : "No"}
+
+
+ Amount of moves made: {movesMade}
+ Is game finished?: {isGameFinished ? "Yes" : "No"}
+
+
-----------------------------------------------------------------------
+
+ );
+ })}
diff --git a/packages/nextjs/types/TicTacToeTypes.ts b/packages/nextjs/types/TicTacToeTypes.ts
index c457938..8e108ac 100644
--- a/packages/nextjs/types/TicTacToeTypes.ts
+++ b/packages/nextjs/types/TicTacToeTypes.ts
@@ -1,6 +1,24 @@
-export type NewGameProps = {
+export type GameCreatedProps = {
gameId: number;
player1: string;
player2: string;
bet: number;
};
+
+export type GameAcceptedProps = {
+ gameId: number;
+ player1: string;
+ player2: string;
+};
+
+export type MoveMadeProps = {
+ gameId: number;
+ player: string;
+ position: number;
+};
+
+export type GameFinishedProps = {
+ gameId: number;
+ winner: string;
+ state: number;
+};