diff --git a/packages/backend/controllers/Admin.ts b/packages/backend/controllers/Admin.ts index 7516113..221bd27 100644 --- a/packages/backend/controllers/Admin.ts +++ b/packages/backend/controllers/Admin.ts @@ -243,3 +243,30 @@ export const kickPlayer = async (req: Request, res: Response) => { res.status(500).json({ error: (err as Error).message }); } }; + +export const varyHiddenPrivatekey = async (req: Request, res: Response) => { + try { + const { id } = req.params; + const { hiddenChars, hiddenPrivateKey, diceCount } = req.body; + const game = await Game.findById(id); + + if (!game) { + return res.status(404).json({ error: "Game not found." }); + } + + if (diceCount < 1 || diceCount > 64) { + return res.status(400).json({ error: "Invalid dice count." }); + } + + game.hiddenChars = hiddenChars; + game.hiddenPrivateKey = hiddenPrivateKey; + game.diceCount = diceCount; + const updatedGame = await game.save(); + const channel = ably.channels.get(`gameUpdate`); + channel.publish(`gameUpdate`, updatedGame); + + res.status(200).json(updatedGame); + } catch (err) { + res.status(500).json({ error: (err as Error).message }); + } +}; diff --git a/packages/backend/models/Game.ts b/packages/backend/models/Game.ts index c012dd0..7d47211 100644 --- a/packages/backend/models/Game.ts +++ b/packages/backend/models/Game.ts @@ -32,7 +32,7 @@ const gameSchema = new mongoose.Schema( }, hiddenPrivateKey: { type: String, - required: false, + required: true, }, hiddenChars: { type: Object, diff --git a/packages/backend/routes/admin.ts b/packages/backend/routes/admin.ts index bb0279d..1a23a17 100644 --- a/packages/backend/routes/admin.ts +++ b/packages/backend/routes/admin.ts @@ -1,5 +1,5 @@ import express from "express"; -import { createGame, changeGameMode, pauseGame, resumeGame, kickPlayer, restartWithNewPk } from "../controllers/Admin"; +import { createGame, changeGameMode, pauseGame, resumeGame, kickPlayer, restartWithNewPk, varyHiddenPrivatekey } from "../controllers/Admin"; import { verifyToken } from "../middleware/auth"; const router = express.Router(); @@ -10,5 +10,6 @@ router.patch("/pause/:id", verifyToken, pauseGame); router.patch("/resume/:id", verifyToken, resumeGame); router.patch("/kickplayer/:id", verifyToken, kickPlayer); router.patch("/restartwithnewpk/:id", verifyToken, restartWithNewPk); +router.patch("/varyhiddenprivatekey/:id", verifyToken, varyHiddenPrivatekey); export default router; diff --git a/packages/nextjs/pages/game/[id].tsx b/packages/nextjs/pages/game/[id].tsx index 998cc07..813dcd2 100644 --- a/packages/nextjs/pages/game/[id].tsx +++ b/packages/nextjs/pages/game/[id].tsx @@ -5,7 +5,12 @@ import Ably from "ably"; import QRCode from "qrcode.react"; import CopyToClipboard from "react-copy-to-clipboard"; import { useAccount, useBalance } from "wagmi"; -import { CheckCircleIcon, DocumentDuplicateIcon } from "@heroicons/react/24/outline"; +import { + CheckCircleIcon, + ChevronDoubleDownIcon, + ChevronDoubleUpIcon, + DocumentDuplicateIcon, +} from "@heroicons/react/24/outline"; import HostAnnouncement from "~~/components/dicedemo/HostAnnouncement"; import PlayerAnnouncement from "~~/components/dicedemo/PlayerAnnoucement"; import RestartWithNewPk from "~~/components/dicedemo/RestartWithNewPk"; @@ -14,7 +19,7 @@ import { Price } from "~~/components/scaffold-eth/Price"; import useGameData from "~~/hooks/useGameData"; import useSweepWallet from "~~/hooks/useSweepWallet"; import { Game } from "~~/types/game/game"; -import { kickPlayer, pauseResumeGame, toggleMode } from "~~/utils/diceDemo/apiUtils"; +import { kickPlayer, pauseResumeGame, toggleMode, varyHiddenPrivatekey } from "~~/utils/diceDemo/apiUtils"; import { calculateLength, compareResult, generateRandomHex } from "~~/utils/diceDemo/gameUtils"; function GamePage() { @@ -357,9 +362,31 @@ function GamePage() {

PRIVATE KEY

-

- {Object.values(game?.hiddenPrivateKey)} -

+
+

+ {Object.values(game?.hiddenPrivateKey)} +

+
+ + +
+
)} @@ -387,9 +414,31 @@ function GamePage() {

PRIVATE KEY

-

- {Object.values(game?.hiddenPrivateKey)} -

+
+

+ {Object.values(game?.hiddenPrivateKey)} +

+
+ + +
+
)} diff --git a/packages/nextjs/server.config.ts b/packages/nextjs/server.config.ts index 9121921..1ff75de 100644 --- a/packages/nextjs/server.config.ts +++ b/packages/nextjs/server.config.ts @@ -1,5 +1,5 @@ const serverConfig = { - isLocal: false, + isLocal: true, localUrl: "http://localhost:6001", liveUrl: "https://rich-ruby-cygnet-tie.cyclic.app/", }; diff --git a/packages/nextjs/utils/diceDemo/apiUtils.ts b/packages/nextjs/utils/diceDemo/apiUtils.ts index 1cd33e6..9fffe0a 100644 --- a/packages/nextjs/utils/diceDemo/apiUtils.ts +++ b/packages/nextjs/utils/diceDemo/apiUtils.ts @@ -59,8 +59,49 @@ export const kickPlayer = async (game: Game, token: string, playerAddress: strin }); const responseData = await response.json(); + notification.success("Kicked " + playerAddress); if (responseData.error) { notification.error(responseData.error); return; } }; + +export const varyHiddenPrivatekey = async (game: Game, token: string, vary: "increase" | "decrease") => { + let hiddenPrivateKey = game?.hiddenPrivateKey; + const hiddenChars = game?.hiddenChars; + const privateKey = game?.privateKey; + let diceCount = game?.diceCount; + + const hiddCharsCopy = { ...hiddenChars }; + + if (vary === "increase") { + hiddenPrivateKey = "*".repeat(diceCount + 1) + privateKey.slice(diceCount + 1); + hiddCharsCopy[diceCount] = privateKey[diceCount]; + diceCount++; + } else { + hiddenPrivateKey = "*".repeat(diceCount - 1) + privateKey.slice(diceCount - 1); + delete hiddCharsCopy[diceCount - 1]; + diceCount--; + } + + if (diceCount < 1 || diceCount > 64) { + notification.error("Invalid dice count."); + return; + } + + try { + await fetch(`${serverUrl}/admin/varyhiddenprivatekey/${game?._id}`, { + method: "PATCH", + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ hiddenChars: hiddCharsCopy, hiddenPrivateKey: hiddenPrivateKey, diceCount: diceCount }), + }); + + notification.success("Updated hidden characters"); + } catch (error) { + notification.error((error as Error).message); + return; + } +};