diff --git a/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-2-core-app-logic.md b/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-2-core-app-logic.md index c912657..2cabf5f 100644 --- a/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-2-core-app-logic.md +++ b/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-2-core-app-logic.md @@ -24,7 +24,7 @@ import { type ShieldedWalletClient, createShieldedWalletClient, } from "seismic-viem"; -import { Abi, Address, Chain, http } from "viem"; +import { Abi, Address, Chain, http, hexToString } from "viem"; import { privateKeyToAccount } from "viem/accounts"; import { getShieldedContractWithCheck } from "../lib/utils"; @@ -144,6 +144,7 @@ async rob(playerName: string) { console.log(`- Player ${playerName} reading rob()`) const contract = this.getPlayerContract(playerName) const result = await contract.read.rob() // signed read - console.log(`- Player ${playerName} robbed secret:`, result) + const decoded = hexToString(result as `0x${string}`) + console.log(`- Player ${playerName} robbed secret:`, decoded) } ``` diff --git a/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-3-bringing-it-all-together.md b/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-3-bringing-it-all-together.md index 56bac81..28476be 100644 --- a/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-3-bringing-it-all-together.md +++ b/docs/gitbook/tutorials/clown-beatdown/building-the-cli/chapter-3-bringing-it-all-together.md @@ -20,6 +20,7 @@ Open `.env` and paste the following: ```properties CHAIN_ID=31337 +VITE_CHAIN_ID=31337 RPC_URL=http://127.0.0.1:8545 ALICE_PRIVKEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 BOB_PRIVKEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d @@ -27,7 +28,8 @@ BOB_PRIVKEY=0x59c6995e998f97a5a0044966f0945389dc9e86dae88c7a8412f4603b6b78690d **What's Happening Here?** -- `CHAIN_ID=31337`: `31337` is the default chain ID for `sanvil` (your local Seismic node). +- `CHAIN_ID=31337`: Used to locate the deployment broadcast file for the correct chain. +- `VITE_CHAIN_ID=31337`: Used for chain selection (`sanvil` vs testnet). `31337` is the default chain ID for `sanvil` (your local Seismic node). - `RPC_URL=http://127.0.0.1:8545`: This is the RPC URL for interacting with the local Seismic node. - `ALICE_PRIVKEY` and `BOB_PRIVKEY`: These are Alice and Bob's private keys, allowing them to play the game. (These are standard test keys provided by `sanvil`) diff --git a/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-1-project-setup-and-providers.md b/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-1-project-setup-and-providers.md index 20ded8b..4af5c88 100644 --- a/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-1-project-setup-and-providers.md +++ b/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-1-project-setup-and-providers.md @@ -31,6 +31,12 @@ bun add seismic-react@1.1.1 seismic-viem@1.1.1 viem@^2.22.3 \ @tailwindcss/vite tailwindcss@^4 ``` +The Vite config below uses the SWC plugin for faster builds. Install it as a dev dependency: + +```bash +bun add -d @vitejs/plugin-react-swc +``` + ### Copy public assets Copy the `public/` folder from the [seismic-starter](https://github.com/SeismicSystems/seismic-starter) repo into `packages/web/public/`. This includes the clown sprites, button images, background, logo, and audio files used by the game UI. @@ -88,7 +94,7 @@ import { } from 'seismic-react' import { sanvil, seismicTestnet } from 'seismic-react/rainbowkit' import { http } from 'viem' -import { Config, WagmiProvider } from 'wagmi' +import { type Config, WagmiProvider } from 'wagmi' import { AuthProvider } from '@/components/chain/WalletConnectButton' import Home from '@/pages/Home' @@ -188,6 +194,56 @@ The provider stack nests four layers, each adding functionality: The `onAddressChange` handler auto-funds new wallets when running on `sanvil` (local dev), so you don't need to manually send ETH to test accounts. +### Supporting files + +Before wiring up the entry point, create the supporting modules that `main.tsx` and `App.tsx` will import. + +**Redux store** — Create `src/store/store.ts`: + +```typescript +import { configureStore } from '@reduxjs/toolkit' + +export const store = configureStore({ + reducer: {}, +}) +``` + +**MUI theme** — Create `src/theme.ts`: + +```typescript +import { createTheme } from '@mui/material/styles' + +const theme = createTheme({ + palette: { + mode: 'dark', + }, +}) + +export default theme +``` + +**Page components** — Create `src/pages/Home.tsx`: + +```typescript +import ClownPuncher from '@/components/game/ClownPuncher' + +const Home = () => +export default Home +``` + +Create `src/pages/NotFound.tsx`: + +```typescript +const NotFound = () =>
404 - Page not found
+export default NotFound +``` + +**Stylesheets** — Create `src/App.css` (empty for now) and replace `src/index.css` with: + +```css +@import "tailwindcss"; +``` + ### Entry point: main.tsx Create `src/main.tsx` to bootstrap the app with theme and state management: diff --git a/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-2-contract-hooks.md b/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-2-contract-hooks.md index 369bc3e..494bd5a 100644 --- a/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-2-contract-hooks.md +++ b/docs/gitbook/tutorials/clown-beatdown/building-the-frontend/chapter-2-contract-hooks.md @@ -16,7 +16,21 @@ cp packages/contracts/out/ClownBeatdown.sol/ClownBeatdown.json \ packages/web/src/abis/contracts/ClownBeatdown.json ``` -You'll also need to add the deployed contract address and chain ID to the JSON file. The ABI file should contain `abi`, `address`, and `chainId` fields. +You'll also need to add the deployed contract address and chain ID to the JSON file. After copying, edit the file to include `address` and `chainId` at the top level. The final structure should look like: + +```json +{ + "address": "0xYourDeployedAddress", + "chainId": 31337, + "abi": [ + { "type": "constructor", "inputs": [...] }, + { "type": "function", "name": "hit", ... }, + ... + ] +} +``` + +You can find the deployed address in `packages/contracts/broadcast/ClownBeatdown.s.sol/31337/run-latest.json` under `transactions[0].contractAddress`. ### Contract type definition @@ -58,8 +72,8 @@ This hook wraps the contract methods into callable functions with proper error h import { useCallback, useEffect, useState } from "react"; import { useShieldedWallet } from "seismic-react"; import { - ShieldedPublicClient, - ShieldedWalletClient, + type ShieldedPublicClient, + type ShieldedWalletClient, addressExplorerUrl, txExplorerUrl, } from "seismic-viem"; @@ -181,6 +195,40 @@ Notice the different contract namespaces used for each method: This distinction between `twrite`, `read`, and `tread` is the key difference from a standard Ethereum dApp. +### Supporting components + +Before building the game actions hook, create the helper components and hooks it depends on. + +**Explorer toast** — Create `src/components/chain/ExplorerToast.tsx`: + +```typescript +import React from 'react' + +type ExplorerToastProps = { + url: string + text: string + hash: string +} + +export const ExplorerToast: React.FC = ({ url, text, hash }) => ( + + {text}{hash.slice(0, 10)}... + +) +``` + +**Toast notifications** — Create `src/hooks/useToastNotifications.ts`: + +```typescript +import { toast } from 'react-toastify' + +export const useToastNotifications = () => ({ + notifySuccess: (msg: string) => toast.success(msg), + notifyError: (msg: string) => toast.error(msg), + notifyInfo: (msg: string | React.ReactElement) => toast.info(msg), +}) +``` + ### useGameActions hook This hook orchestrates the game logic, managing state and coordinating contract calls with UI feedback. Create `src/hooks/useGameActions.ts`: diff --git a/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-cli.md b/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-cli.md index fc91b65..3d06152 100644 --- a/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-cli.md +++ b/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-cli.md @@ -18,7 +18,7 @@ bun init -y 3. Now, create an `src/` folder and move `index.ts` there. ```bash -mkdir -p src && mv -t src index.ts +mkdir -p src && mv index.ts src/ ``` 4. Now, edit `package.json` to be the following: @@ -33,7 +33,7 @@ mkdir -p src && mv -t src index.ts }, "dependencies": { "dotenv": "^16.4.7", - "seismic-viem": "1.0.9", + "seismic-viem": "1.1.1", "viem": "^2.22.3" }, "devDependencies": { diff --git a/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-contracts.md b/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-contracts.md index 6c73736..8bbfff6 100644 --- a/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-contracts.md +++ b/docs/gitbook/tutorials/clown-beatdown/setting-up-your-project/initialize-contracts.md @@ -9,7 +9,7 @@ cd packages/contracts 2. **Initialize a project with `sforge`:** ```bash -sforge init --no-commit && rm -rf .github +sforge init && rm -rf .github ``` This command will: diff --git a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-1-the-secrets-pool.md b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-1-the-secrets-pool.md index 1fda0c1..aa788d8 100644 --- a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-1-the-secrets-pool.md +++ b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-1-the-secrets-pool.md @@ -8,7 +8,7 @@ In this chapter, you'll learn to create and initialize the secrets pool — a co ### Defining the secrets pool -The **secrets pool** is the collection of hidden strings that the clown carries. Using Seismic's **`sbytes`** type, each secret is shielded on-chain — encrypted and invisible to observers. A shielded **`suint256`** index determines which secret gets revealed when the clown is robbed. Open up `packages/contracts/ClownBeatdown.sol` and define the state variables: +The **secrets pool** is the collection of hidden strings that the clown carries. Using Seismic's **`sbytes`** type, each secret is shielded on-chain — encrypted and invisible to observers. A shielded **`suint256`** index determines which secret gets revealed when the clown is robbed. Open up `packages/contracts/src/ClownBeatdown.sol` and define the state variables: ```solidity // SPDX-License-Identifier: MIT License @@ -26,6 +26,8 @@ contract ClownBeatdown { } ``` +We accept `_clownStamina` in the constructor but won't use it until Chapter 2, when we add the stamina system. + ### Add the addSecret function Next, let's implement a function to add secrets to the pool. The `addSecret` function takes a plain `string` and converts it to `sbytes` for shielded storage: diff --git a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-3-reset-mechanism-rounds-and-contributor-access.md b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-3-reset-mechanism-rounds-and-contributor-access.md index 1f48e46..43b8f4c 100644 --- a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-3-reset-mechanism-rounds-and-contributor-access.md +++ b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/chapter-3-reset-mechanism-rounds-and-contributor-access.md @@ -118,7 +118,7 @@ contract ClownBeatdown { // Tracks the number of hits per player per round. mapping(uint256 => mapping(address => uint256)) hitsPerRound; - // Events to log hits, shakes, and resets. + // Events to log hits and resets. // Event to log hits. event Hit(uint256 indexed round, address indexed hitter, uint256 remaining); // Logged when a hit lands. diff --git a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/deploying.md b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/deploying.md index 51910d0..b61438c 100644 --- a/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/deploying.md +++ b/docs/gitbook/tutorials/clown-beatdown/writing-the-contract/deploying.md @@ -31,17 +31,14 @@ contract ClownBeatdownScript is Script { vm.startBroadcast(deployerPrivateKey); clownBeatdown = new ClownBeatdown(3); - clownBeatdown.addSecret("The moon is made of cheese"); - clownBeatdown.addSecret("Clowns rule the underworld"); - clownBeatdown.addSecret("The cake is a lie"); - clownBeatdown.addSecret("42 is the answer"); - clownBeatdown.addSecret("Never trust a smiling clown"); vm.stopBroadcast(); + + console.log("Deployed at:", address(clownBeatdown)); } } ``` -This script will deploy a new instance of the ClownBeatdown contract with an initial stamina of 3 and populate it with 5 secrets. +This script will deploy a new instance of the ClownBeatdown contract with an initial stamina of 3. We'll add secrets separately in the next step, since `addSecret` performs shielded writes that need to be sent as on-chain transactions. ### Deploying the contract @@ -62,7 +59,7 @@ PRIVKEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 The `RPC_URL` denotes the port on which `sanvil` is running and the `PRIVKEY` is one of the standard `sanvil` testing private keys. -3. Now, from `packages/contracts`, run +3. Now, from `packages/contracts`, deploy the contract: ```bash source .env @@ -71,4 +68,21 @@ sforge script script/ClownBeatdown.s.sol:ClownBeatdownScript \ --broadcast ``` -Your contract should be up and deployed to your local Seismic node! +The output will show the deployed contract address (e.g. `0x5FbDB2315678afecb367f032d93F642f64180aa3`). + +4. Add secrets to the deployed contract using `scast send`. Replace `` with the address from the previous step: + +```bash +scast send "addSecret(string)" "The moon is made of cheese" \ + --rpc-url $RPC_URL --private-key $PRIVKEY +scast send "addSecret(string)" "Clowns rule the underworld" \ + --rpc-url $RPC_URL --private-key $PRIVKEY +scast send "addSecret(string)" "The cake is a lie" \ + --rpc-url $RPC_URL --private-key $PRIVKEY +scast send "addSecret(string)" "42 is the answer" \ + --rpc-url $RPC_URL --private-key $PRIVKEY +scast send "addSecret(string)" "Never trust a smiling clown" \ + --rpc-url $RPC_URL --private-key $PRIVKEY +``` + +Your contract should be up and deployed to your local Seismic node with 5 secrets!