Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .env.production
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# no trailing slash
NEXT_PUBLIC_WORKER_DOMAIN=chess-worker.johnsgresham.workers.dev
NEXT_PUBLIC_URL=https://basedchess.xyz
NEXT_PUBLIC_NEYNAR_API_KEY_FRNT=47FB9C28-6FFC-4086-84C3-ED9B88DBAF27
# NEXT_PUBLIC_WORKER_DOMAIN=chess-worker.johnsgresham.workers.dev
# NEXT_PUBLIC_URL=https://basedchess.xyz
# NEXT_PUBLIC_NEYNAR_API_KEY_FRNT=47FB9C28-6FFC-4086-84C3-ED9B88DBAF27

# staging because passing env vars is broken in opennextjs-cloudflare
# NEXT_PUBLIC_URL=https://based-chess-worker-nextjs-staging.johnsgresham.workers.dev
# NEXT_PUBLIC_WORKER_DOMAIN=chess-worker-staging.johnsgresham.workers.dev
# NEXT_PUBLIC_URL=https://staging.basedchess.xyz
# NEXT_PUBLIC_NEYNAR_API_KEY_FRNT=47FB9C28-6FFC-4086-84C3-ED9B88DBAF27
NEXT_PUBLIC_WORKER_DOMAIN=chess-worker-staging.johnsgresham.workers.dev
NEXT_PUBLIC_URL=https://sub-accounts-demo.basedchess.xyz
NEXT_PUBLIC_NEYNAR_API_KEY_FRNT=47FB9C28-6FFC-4086-84C3-ED9B88DBAF27
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"cf-typegen": "wrangler types --env-interface CloudflareEnv cloudflare-env.d.ts"
},
"dependencies": {
"@coinbase/wallet-sdk": "4.4.0-canary.20250402",
"@farcaster/frame-sdk": "^0.0.32",
"@farcaster/frame-wagmi-connector": "^0.0.20",
"@radix-ui/react-accordion": "^1.2.3",
Expand Down
80 changes: 80 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 4 additions & 2 deletions src/app/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { ArrowUpRight } from "lucide-react";
import { contracts, type SupportedChainId } from "../lib/contracts";
import { blockExplorers } from "../lib/contracts";
import { buttonVariants } from "../components/ui/button";
import { useAccount } from "wagmi";
// import { useAccount } from "wagmi";
import Link from "next/link";
import { DarkModeToggle } from "../components/DarkModeToggle";
import { DevModeToggle } from "../components/DevModeToggle";
// import { useCoinbaseWallet } from "../context/CoinbaseWalletContext";

export const Footer = () => {
const { chainId } = useAccount();
// const { chainId } = useAccount();
const chainId: SupportedChainId = 84532;

return (
<div className="flex flex-col w-full space-between items-center justify-center pt-16 pb-8 pr-8 pl-8 gap-2">
Expand Down
74 changes: 62 additions & 12 deletions src/app/games/[gameId]/game.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ import { MintGameWinNFTBtn, type MintStep } from "./MintGameWinNFTBtn";
import { useDevMode } from "../../../components/hooks/useLocalSettings";
import { useFarcasterUser } from "../../../components/hooks/useFarcasterUser";
import { FarcasterUser } from "../../../lib/neynar.server";
import { useCoinbaseWallet } from "../../../context/CoinbaseWalletContext";
import { recoverMessageAddress } from "viem";

export type WsMessage = {
type: string;
Expand Down Expand Up @@ -84,7 +86,7 @@ export default function Game() {
const wsRef = useRef<WebSocket | null>(null);
const chessboardRef = useRef<HTMLDivElement>(null);
const [game, setGame] = useState<Chess | undefined>();
const { address, isConnected } = useAccount();
// const { address, isConnected } = useAccount();
const [awaitSigningMove, setAwaitSigningMove] = useState(false);
const [boardOrientation, setBoardOrientation] = useState<BoardOrientation>("white");
const params = useParams();
Expand Down Expand Up @@ -136,8 +138,8 @@ export default function Game() {
>({});

const { showToast, Toast } = useToast();
const chainId = useChainId();

// const chainId = useChainId();
const chainId: SupportedChainId = 84532;
const [winner, setWinner] = useState<`0x${string}` | undefined>();
const [isNFTMinted, setIsNFTMinted] = useState(false);
const [isNFTReadyToMint, setIsNFTReadyToMint] = useState(false);
Expand Down Expand Up @@ -177,6 +179,47 @@ export default function Game() {
args: [contracts.gamesContract[chainId as SupportedChainId].address, contractGameId],
});

// [start] Coinbase Sub Account Wallet specifics
const {
isConnected,
connect,
disconnect,
address,
subAccount,
createSubAccount,
subAccountWalletClient,
provider,
} = useCoinbaseWallet();
const [signature, setSignature] = useState<string | null>(null);

const signMessageSubAccount = useCallback(
async (message: string) => {
if (!subAccountWalletClient || !subAccount) {
// open create sub account for user
createSubAccount();
console.error("Subaccount wallet client or subaccount not found");
throw new Error("Subaccount wallet client or subaccount not found");
}

const signature = await subAccountWalletClient.signMessage({
message,
account: subAccount,
});
console.log("signature", signature);
// Error: Invalid yParityOrV value
// const addr = await recoverMessageAddress({
// message,
// signature,
// });
// console.log("recoverMessageAddress addr", addr);

setSignature(signature);
return signature;
},
[subAccountWalletClient, subAccount, createSubAccount],
);
// [end] Coinbase Sub Account Wallet specifics

useEffect(() => {
setAudioPlayerDropChessPiece(new Audio("/sounds/drop_piece.mp3"));
setAudioPlayerLoseGame(new Audio("/sounds/lose_game.mp3"));
Expand Down Expand Up @@ -678,17 +721,21 @@ export default function Game() {
// sign move
const message = game.pgn();
// const message = JSON.stringify(moveMove.lan)
const signature = await signMessage(frameWagmiConfig, {
message,
});
// const signature = await signMessage(frameWagmiConfig, {
// message,
// });
const signature = await signMessageSubAccount(message);

console.log("user move signature:", signature);

const verified = await verifyMessage(frameWagmiConfig, {
address,
message,
signature,
});
console.log("user move signature verified:", verified);
// todo: verify the sub account signature

// const verified = await verifyMessage(frameWagmiConfig, {
// address,
// message,
// signature,
// });
// console.log("user move signature verified:", verified);

setAwaitSigningMove(false);
// update server
Expand Down Expand Up @@ -718,6 +765,7 @@ export default function Game() {
signature,
message,
address,
subAccount,
},
}),
);
Expand All @@ -744,6 +792,7 @@ export default function Game() {
signature,
message,
address,
subAccount,
},
}),
);
Expand All @@ -770,6 +819,7 @@ export default function Game() {
signature,
message,
address,
subAccount,
},
}),
);
Expand Down
39 changes: 36 additions & 3 deletions src/app/header.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
"use client";

import { Button } from "../components/ui/button";
import Link from "next/link";
import Image from "next/image";
import { ConnectButton } from "@rainbow-me/rainbowkit";
import { useCoinbaseWallet } from "../context/CoinbaseWalletContext";
import DisplayAddress from "../components/util/DisplayAddress";

export const Header = () => {
const { isConnected, connect, disconnect, address, subAccount, createSubAccount } =
useCoinbaseWallet();

return (
<div className="flex sm:flex-row flex-wrap items-center justify-between w-full p-2">
<Link href={"/"}>
Expand All @@ -22,10 +28,37 @@ export const Header = () => {
<div className="text-xs text-green-500">DEV</div>
)}
{process.env.NEXT_PUBLIC_WORKER_DOMAIN?.includes("staging") && (
<div className="text-xs text-yellow-500">STAGING</div>
<div className="text-xs text-yellow-500">Sub Accounts Demo</div>
)}
<div>
<ConnectButton />
{/* <ConnectButton /> */}
{isConnected ? (
<div style={{ display: "flex", flexDirection: "column", gap: "1rem" }}>
<span>
Account: <DisplayAddress address={address} />
</span>

{!subAccount && (
<Button type="button" onClick={createSubAccount} className="w-fit">
<span className="text-xs">Create Sub Account</span>
</Button>
)}

{subAccount && (
<span>
Sub Account: <DisplayAddress address={subAccount} />
</span>
)}

<Button type="button" onClick={disconnect} className="w-fit">
<span className="text-xs">Disconnect Wallet</span>
</Button>
</div>
) : (
<Button type="button" onClick={connect} className="w-fit">
<span className="text-xs">Connect Wallet</span>
</Button>
)}
</div>
</div>
);
Expand Down
Loading