diff --git a/.env.production b/.env.production
index 15155e7..5aef306 100644
--- a/.env.production
+++ b/.env.production
@@ -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
diff --git a/package.json b/package.json
index 40b3e92..5bbdffd 100644
--- a/package.json
+++ b/package.json
@@ -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",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index f6c9799..310502b 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -8,6 +8,9 @@ importers:
.:
dependencies:
+ '@coinbase/wallet-sdk':
+ specifier: 4.4.0-canary.20250402
+ version: 4.4.0-canary.20250402(@types/react@19.0.12)(bufferutil@4.0.9)(react@19.1.0)(typescript@5.8.2)(use-sync-external-store@1.4.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.24.2)
'@farcaster/frame-sdk':
specifier: ^0.0.32
version: 0.0.32(typescript@5.8.2)(zod@3.24.2)
@@ -755,6 +758,9 @@ packages:
'@coinbase/wallet-sdk@4.3.0':
resolution: {integrity: sha512-T3+SNmiCw4HzDm4we9wCHCxlP0pqCiwKe4sOwPH3YAK2KSKjxPRydKu6UQJrdONFVLG7ujXvbd/6ZqmvJb8rkw==}
+ '@coinbase/wallet-sdk@4.4.0-canary.20250402':
+ resolution: {integrity: sha512-moQz9aI1+poE49lXFqtTqdg7HeJLEydGEYInSeDJPPV18La2RUUUSnwFEqqufPPE8edIVtbRt4FTy0qyawuMMg==}
+
'@cspotcode/source-map-support@0.8.1':
resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==}
engines: {node: '>=12'}
@@ -4502,6 +4508,9 @@ packages:
resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==}
engines: {node: ^10 || ^12 || >=14}
+ preact@10.24.2:
+ resolution: {integrity: sha512-1cSoF0aCC8uaARATfrlz4VCBqE8LwZwRfLgkxJOQwAlQt6ayTmi0D9OF7nXid1POI5SZidFuG9CnlXbDfLqY/Q==}
+
preact@10.26.4:
resolution: {integrity: sha512-KJhO7LBFTjP71d83trW+Ilnjbo+ySsaAgCfXOXUlmGzJ4ygYPWmysm77yg4emwfmoz3b22yvH5IsVFHbhUaH5w==}
@@ -5222,6 +5231,14 @@ packages:
resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==}
engines: {node: '>= 0.8'}
+ viem@2.22.17:
+ resolution: {integrity: sha512-eqNhlPGgRLR29XEVUT2uuaoEyMiaQZEKx63xT1py9OYsE+ZwlVgjnfrqbXad7Flg2iJ0Bs5Hh7o0FfRWUJGHvg==}
+ peerDependencies:
+ typescript: '>=5.0.4'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
viem@2.23.2:
resolution: {integrity: sha512-NVmW/E0c5crMOtbEAqMF0e3NmvQykFXhLOc/CkLIXOlzHSA6KXVz3CYVmaKqBF8/xtjsjHAGjdJN3Ru1kFJLaA==}
peerDependencies:
@@ -5433,6 +5450,24 @@ packages:
use-sync-external-store:
optional: true
+ zustand@5.0.3:
+ resolution: {integrity: sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==}
+ engines: {node: '>=12.20.0'}
+ peerDependencies:
+ '@types/react': '>=18.0.0'
+ immer: '>=9.0.6'
+ react: '>=18.0.0'
+ use-sync-external-store: '>=1.2.0'
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ immer:
+ optional: true
+ react:
+ optional: true
+ use-sync-external-store:
+ optional: true
+
snapshots:
'@adraffy/ens-normalize@1.11.0': {}
@@ -7095,6 +7130,26 @@ snapshots:
eventemitter3: 5.0.1
preact: 10.26.4
+ '@coinbase/wallet-sdk@4.4.0-canary.20250402(@types/react@19.0.12)(bufferutil@4.0.9)(react@19.1.0)(typescript@5.8.2)(use-sync-external-store@1.4.0(react@19.1.0))(utf-8-validate@5.0.10)(zod@3.24.2)':
+ dependencies:
+ '@noble/hashes': 1.4.0
+ clsx: 1.2.1
+ eventemitter3: 5.0.1
+ idb-keyval: 6.2.1
+ ox: 0.6.9(typescript@5.8.2)(zod@3.24.2)
+ preact: 10.24.2
+ viem: 2.22.17(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2)
+ zustand: 5.0.3(@types/react@19.0.12)(react@19.1.0)(use-sync-external-store@1.4.0(react@19.1.0))
+ transitivePeerDependencies:
+ - '@types/react'
+ - bufferutil
+ - immer
+ - react
+ - typescript
+ - use-sync-external-store
+ - utf-8-validate
+ - zod
+
'@cspotcode/source-map-support@0.8.1':
dependencies:
'@jridgewell/trace-mapping': 0.3.9
@@ -11702,6 +11757,8 @@ snapshots:
picocolors: 1.1.1
source-map-js: 1.2.1
+ preact@10.24.2: {}
+
preact@10.26.4: {}
prelude-ls@1.2.1: {}
@@ -12460,6 +12517,23 @@ snapshots:
vary@1.1.2: {}
+ viem@2.22.17(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2):
+ dependencies:
+ '@noble/curves': 1.8.1
+ '@noble/hashes': 1.7.1
+ '@scure/bip32': 1.6.2
+ '@scure/bip39': 1.5.4
+ abitype: 1.0.8(typescript@5.8.2)(zod@3.24.2)
+ isows: 1.0.6(ws@8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10))
+ ox: 0.6.7(typescript@5.8.2)(zod@3.24.2)
+ ws: 8.18.0(bufferutil@4.0.9)(utf-8-validate@5.0.10)
+ optionalDependencies:
+ typescript: 5.8.2
+ transitivePeerDependencies:
+ - bufferutil
+ - utf-8-validate
+ - zod
+
viem@2.23.2(bufferutil@4.0.9)(typescript@5.8.2)(utf-8-validate@5.0.10)(zod@3.24.2):
dependencies:
'@noble/curves': 1.8.1
@@ -12715,3 +12789,9 @@ snapshots:
'@types/react': 19.0.12
react: 19.1.0
use-sync-external-store: 1.4.0(react@19.1.0)
+
+ zustand@5.0.3(@types/react@19.0.12)(react@19.1.0)(use-sync-external-store@1.4.0(react@19.1.0)):
+ optionalDependencies:
+ '@types/react': 19.0.12
+ react: 19.1.0
+ use-sync-external-store: 1.4.0(react@19.1.0)
diff --git a/src/app/footer.tsx b/src/app/footer.tsx
index 7d65b00..86a669d 100644
--- a/src/app/footer.tsx
+++ b/src/app/footer.tsx
@@ -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 (
diff --git a/src/app/games/[gameId]/game.tsx b/src/app/games/[gameId]/game.tsx
index dd78b90..3e17e7e 100644
--- a/src/app/games/[gameId]/game.tsx
+++ b/src/app/games/[gameId]/game.tsx
@@ -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;
@@ -84,7 +86,7 @@ export default function Game() {
const wsRef = useRef
(null);
const chessboardRef = useRef(null);
const [game, setGame] = useState();
- const { address, isConnected } = useAccount();
+ // const { address, isConnected } = useAccount();
const [awaitSigningMove, setAwaitSigningMove] = useState(false);
const [boardOrientation, setBoardOrientation] = useState("white");
const params = useParams();
@@ -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);
@@ -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(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"));
@@ -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
@@ -718,6 +765,7 @@ export default function Game() {
signature,
message,
address,
+ subAccount,
},
}),
);
@@ -744,6 +792,7 @@ export default function Game() {
signature,
message,
address,
+ subAccount,
},
}),
);
@@ -770,6 +819,7 @@ export default function Game() {
signature,
message,
address,
+ subAccount,
},
}),
);
diff --git a/src/app/header.tsx b/src/app/header.tsx
index df6655e..1d0bd53 100644
--- a/src/app/header.tsx
+++ b/src/app/header.tsx
@@ -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 (
@@ -22,10 +28,37 @@ export const Header = () => {
DEV
)}
{process.env.NEXT_PUBLIC_WORKER_DOMAIN?.includes("staging") && (
-
STAGING
+
Sub Accounts Demo
)}
-
+ {/*
*/}
+ {isConnected ? (
+
+
+ Account:
+
+
+ {!subAccount && (
+
+ )}
+
+ {subAccount && (
+
+ Sub Account:
+
+ )}
+
+
+
+ ) : (
+
+ )}
);
diff --git a/src/app/page.tsx b/src/app/page.tsx
index 1f5c2c4..bd3e440 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -10,6 +10,7 @@ import GameSummary from "../components/GameSummary";
import { Separator } from "@/components/ui/separator";
import { useSetFarcasterContext } from "../components/hooks/useFarcasterContext";
import type { FarcasterUser } from "../lib/neynar.server";
+import { useCoinbaseWallet } from "../context/CoinbaseWalletContext";
// export function metadata() {
// return [
@@ -61,11 +62,21 @@ export type GameData = {
export default function Page() {
const [games, setGames] = useState([]);
- const { address } = useAccount();
+ // const { address } = useAccount();
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState();
const [errorFetchGames, setErrorFetchGames] = useState("");
const { mutate: setFarcasterContext } = useSetFarcasterContext();
+ const {
+ isConnected,
+ connect,
+ disconnect,
+ address,
+ subAccount,
+ createSubAccount,
+ subAccountWalletClient,
+ provider,
+ } = useCoinbaseWallet();
useEffect(() => {
const load = async () => {
diff --git a/src/components/NewGameSheet.tsx b/src/components/NewGameSheet.tsx
index f63a886..dd77fdc 100644
--- a/src/components/NewGameSheet.tsx
+++ b/src/components/NewGameSheet.tsx
@@ -25,6 +25,7 @@ import { useConnectModal } from "@rainbow-me/rainbowkit";
import SearchSelectUser, { type User as FarcasterUserSelect } from "./SearchSelectUser";
import { Tabs, TabsTrigger, TabsList, TabsContent } from "@/components/ui/tabs";
import { useFarcasterContext } from "./hooks/useFarcasterContext";
+import { useCoinbaseWallet } from "../context/CoinbaseWalletContext";
export default function NewGameSheet() {
const [open, setOpen] = useState(false);
@@ -38,12 +39,22 @@ export default function NewGameSheet() {
const [openAfterConnect, setOpenAfterConnect] = useState(false);
const [errorCreateGame, setErrorCreateGame] = useState("");
const router = useRouter();
- const { address } = useAccount();
+ // const { address } = useAccount();
const { openConnectModal } = useConnectModal();
const { data: farcasterContext } = useFarcasterContext();
const [selectedFarcasterUser, setSelectedFarcasterUser] = useState(
null,
);
+ const {
+ isConnected,
+ connect,
+ disconnect,
+ address,
+ subAccount,
+ createSubAccount,
+ subAccountWalletClient,
+ provider,
+ } = useCoinbaseWallet();
useEffect(() => {
if (openAfterConnect && address) {
diff --git a/src/components/providers/providers.tsx b/src/components/providers/providers.tsx
index 029ffc7..734a263 100644
--- a/src/components/providers/providers.tsx
+++ b/src/components/providers/providers.tsx
@@ -6,6 +6,7 @@ import { useState, useEffect } from "react";
import { darkTheme } from "@rainbow-me/rainbowkit";
import { ThemeProvider } from "@/components/providers/theme-provider";
import { useTheme } from "next-themes";
+import { CoinbaseWalletProvider } from "@/context/CoinbaseWalletContext";
export default function Providers({ children }: { children: React.ReactNode }) {
const [mounted, setMounted] = useState(false);
@@ -43,15 +44,17 @@ export default function Providers({ children }: { children: React.ReactNode }) {
return (
- {/* To provide theme for RainbowKit in Providers */}
-
- {children}
-
+
+ {/* To provide theme for RainbowKit in Providers */}
+
+ {children}
+
+
);
diff --git a/src/components/util/DisplayAddress.tsx b/src/components/util/DisplayAddress.tsx
index 9836736..37ba768 100644
--- a/src/components/util/DisplayAddress.tsx
+++ b/src/components/util/DisplayAddress.tsx
@@ -4,8 +4,7 @@ import { mainnetConfig } from "../../lib/wagmiconfig";
import { normalize } from "viem/ens";
import { EmojiAvatar } from "./EmojiAvatar";
import type { FarcasterUser } from "../../lib/neynar.server";
-import { Check } from "lucide-react";
-import { Copy } from "lucide-react";
+import { Check, Copy } from "lucide-react";
import { useState } from "react";
// Displays an ethereum address in a truncated format by showing the first 6 and last 4 characters
@@ -43,7 +42,7 @@ export default function DisplayAddress({
};
return (
-
+
Promise;
+ disconnect: () => void;
+ isConnected: boolean;
+ address: Address | null;
+ subAccount: Address | null;
+ createSubAccount: () => Promise;
+ subAccountWalletClient: WalletClient | null;
+}
+
+const CoinbaseWalletContext = createContext({
+ provider: null,
+ connect: async () => {},
+ disconnect: () => {},
+ isConnected: false,
+ address: null,
+ subAccount: null,
+ createSubAccount: async () => null,
+ subAccountWalletClient: null,
+});
+
+export function CoinbaseWalletProvider({ children }: { children: ReactNode }) {
+ const [provider, setProvider] = useState(null);
+ const [isConnected, setIsConnected] = useState(false);
+ const [address, setAddress] = useState(null);
+ const [subAccount, setSubAccount] = useState(null);
+ const [subAccountWalletClient, setSubAccountWalletClient] = useState(null);
+
+ useEffect(() => {
+ // Initialize Coinbase Wallet SDK
+ const coinbaseWalletSDK = createCoinbaseWalletSDK({
+ appName: "Based Chess x Coinbase Sub Account demo",
+ appChainIds: [baseSepolia.id],
+ preference: {
+ options: "smartWalletOnly",
+ keysUrl: "https://keys-dev.coinbase.com/connect",
+ },
+ toSubAccountSigner: getCryptoKeyAccount,
+ });
+ setProvider(coinbaseWalletSDK.getProvider());
+ }, []);
+
+ // Add public client for account creation
+ const publicClient = useMemo(
+ () =>
+ createPublicClient({
+ chain: baseSepolia,
+ transport: http(),
+ }),
+ [],
+ );
+
+ // Add a new useEffect to initialize a Sub Account wallet client when Sub Account is created
+ useEffect(() => {
+ async function initializeSubAccountClient() {
+ if (!subAccount || !provider || !publicClient) {
+ setSubAccountWalletClient(null);
+ return;
+ }
+
+ try {
+ const signer = await getCryptoKeyAccount();
+ if (!signer) {
+ throw new Error("Signer not found");
+ }
+
+ const account = await toCoinbaseSmartAccount({
+ client: publicClient,
+ owners: [signer.account as WebAuthnAccount],
+ address: subAccount,
+ });
+
+ const client = createWalletClient({
+ account,
+ chain: baseSepolia,
+ transport: custom({
+ async request({ method, params }) {
+ const response = await provider.request({ method, params });
+ return response;
+ },
+ }),
+ });
+
+ setSubAccountWalletClient(client);
+ } catch (error) {
+ console.error("Failed to initialize subAccount wallet client:", error);
+ setSubAccountWalletClient(null);
+ }
+ }
+
+ initializeSubAccountClient();
+ }, [subAccount, provider, publicClient]);
+
+ const walletClient = useMemo(() => {
+ if (!provider) return null;
+ return createWalletClient({
+ chain: baseSepolia,
+ transport: custom({
+ async request({ method, params }) {
+ const response = await provider.request({ method, params });
+ return response;
+ },
+ }),
+ });
+ }, [provider]);
+
+ const connect = useCallback(async () => {
+ if (!walletClient || !provider) return;
+ walletClient.requestAddresses().then(async (addresses) => {
+ if (addresses.length > 0) {
+ setAddress(addresses[0]);
+ setIsConnected(true);
+ }
+ });
+ }, [walletClient, provider]);
+
+ const disconnect = () => {
+ if (!provider) return;
+ try {
+ provider.disconnect();
+ setIsConnected(false);
+ setAddress(null);
+ } catch (error) {
+ console.error("Failed to disconnect from Coinbase Wallet:", error);
+ }
+ };
+
+ const createSubAccount = useCallback(async () => {
+ if (!provider || !address) {
+ throw new Error("Address or provider not found");
+ }
+
+ const signer = await getCryptoKeyAccount();
+
+ const walletConnectResponse = (await provider.request({
+ method: "wallet_connect",
+ params: [
+ {
+ version: "1",
+ capabilities: {
+ addSubAccount: {
+ account: {
+ type: "create",
+ keys: [
+ {
+ type: "webauthn-p256",
+ key: signer.account?.publicKey,
+ },
+ ],
+ },
+ },
+ },
+ },
+ ],
+ })) as {
+ accounts: {
+ address: Address;
+ capabilities: {
+ addSubAccount: {
+ address: Address;
+ };
+ };
+ }[];
+ };
+ const { addSubAccount } = walletConnectResponse.accounts[0].capabilities;
+ const subAccount = addSubAccount.address;
+ setSubAccount(subAccount);
+ return subAccount;
+ }, [provider, address]);
+
+ return (
+
+ {children}
+
+ );
+}
+
+export function useCoinbaseWallet() {
+ const context = useContext(CoinbaseWalletContext);
+ if (context === undefined) {
+ throw new Error("useCoinbaseWallet must be used within a CoinbaseWalletProvider");
+ }
+ return context;
+}
diff --git a/wrangler.jsonc b/wrangler.jsonc
index 32e4f2b..ae70297 100644
--- a/wrangler.jsonc
+++ b/wrangler.jsonc
@@ -13,6 +13,40 @@
"head_sampling_rate": 1
},
"env": {
+ "sub-accounts-demo": {
+ "name": "based-chess-worker-nextjs-sub-accounts-demo",
+ "vars": {
+ "ENVIRONMENT": "staging",
+ "CHAIN_ID": "84532"
+ // "NEXT_PUBLIC_URL": "https://staging.basedchess.xyz",
+ // "NEXT_PUBLIC_WORKER_DOMAIN": "chess-worker-staging.johnsgresham.workers.dev"
+ },
+ // "build": {
+ // "command": "NODE_ENV=staging npm run build"
+ // },
+ "durable_objects": {
+ "bindings": [
+ {
+ "name": "CHESS_GAME",
+ "class_name": "ChessGame",
+ "script_name": "chess-worker-staging"
+ }
+ ]
+ },
+ "services": [
+ {
+ "binding": "RPC_SERVICE",
+ "service": "chess-worker",
+ "entrypoint": "SessionsRPC"
+ }
+ ],
+ "routes": [
+ {
+ "pattern": "sub-accounts-demo.basedchess.xyz/*",
+ "zone_name": "basedchess.xyz"
+ }
+ ]
+ },
"staging": {
"name": "based-chess-worker-nextjs-staging",
"vars": {