From ad34bd5dbe8ae604f6cf409d5f29e26c429571ef Mon Sep 17 00:00:00 2001 From: tash-2s <81064017+tash-2s@users.noreply.github.com> Date: Thu, 15 Feb 2024 20:04:30 -0600 Subject: [PATCH] fix --- .../client-react-external-wallet/src/App.tsx | 155 +++++++++--------- .../src/MUDContext.tsx | 23 --- .../src/mud/getWagmiConfig.ts | 3 +- .../src/mud/networkConfig.tsx | 33 +++- .../src/mud/store.tsx | 37 +++++ 5 files changed, 149 insertions(+), 102 deletions(-) delete mode 100644 examples/minimal/packages/client-react-external-wallet/src/MUDContext.tsx create mode 100644 examples/minimal/packages/client-react-external-wallet/src/mud/store.tsx diff --git a/examples/minimal/packages/client-react-external-wallet/src/App.tsx b/examples/minimal/packages/client-react-external-wallet/src/App.tsx index ee05c4f9b6..93917b3e00 100644 --- a/examples/minimal/packages/client-react-external-wallet/src/App.tsx +++ b/examples/minimal/packages/client-react-external-wallet/src/App.tsx @@ -1,37 +1,23 @@ import { useState, useEffect } from "react"; +import { BaseError } from "viem"; import { usePublicClient, + useWalletClient, useAccount, useConnect, useDisconnect, - useWalletClient, - type WalletClient, - type PublicClient, + useNetwork, + useSwitchNetwork, } from "wagmi"; -import { syncToZustand } from "@latticexyz/store-sync/zustand"; -import { type ContractWrite, getContract } from "@latticexyz/common"; -import { Subject, share } from "rxjs"; +import { share } from "rxjs"; +import { useNetworkConfig, useWorldContract } from "./mud/networkConfig"; +import { syncStore, StoreProvider, useStore, type Store } from "./mud/store"; import mudConfig from "contracts/mud.config"; -import { BaseError, type Hex } from "viem"; -import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; -import { useNetworkConfig, type NetworkConfig } from "./mud/networkConfig"; - -type Store = Awaited>; - -const syncStore = async (networkConfig: NetworkConfig, publicClient: PublicClient) => { - const { tables, useStore, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToZustand({ - config: mudConfig, - address: networkConfig.worldAddress, - publicClient, - startBlock: BigInt(networkConfig.initialBlockNumber), - }); - - return { tables, useStore, latestBlock$, storedBlockLogs$, waitForTransaction }; -}; export const App = () => { const networkConfig = useNetworkConfig(); const publicClient = usePublicClient(); + const { isConnected } = useAccount(); const [store, setStore] = useState(null); @@ -42,75 +28,58 @@ export const App = () => { return ( <> - {store ? : <>} + {isConnected && } + {store && ( + + + + )} ); }; -const getWorldContract = (address: Hex, publicClient: PublicClient, walletClient: WalletClient) => { - const write$ = new Subject(); - const worldContract = getContract({ - address, - abi: IWorldAbi, - publicClient, - walletClient, - onWrite: (write) => write$.next(write), - }); - - return { worldContract, write$ }; -}; +export const Synced = () => { + const store = useStore(); + const { chain } = useNetwork(); + const networkConfig = useNetworkConfig(); + const { data: walletClient } = useWalletClient(); -export const Synced = (props: { store: Store }) => { - const { isConnected } = useAccount(); - // const networkConfig = useNetworkConfig(); - // const publicClient = usePublicClient(); - // const { data: walletClient } = useWalletClient(); - - // const { worldContract, write$ } = _getContract(networkConfig.worldAddress as Hex, publicClient, walletClient!); - - // useEffect(() => { - // if (import.meta.env.DEV) { - // import("@latticexyz/dev-tools").then(({ mount }) => - // mount({ - // config: mudConfig, - // publicClient: publicClient, - // walletClient: walletClient!, - // latestBlock$: props.store.latestBlock$, - // storedBlockLogs$: props.store.storedBlockLogs$, - // worldAddress: worldContract.address, - // worldAbi: worldContract.abi, - // write$: write$.asObservable().pipe(share()), - // useStore: props.store.useStore, - // }) - // ); - // } - // }, [isConnected]); - - const counter = props.store.useStore((state) => state.getValue(props.store.tables.CounterTable, {})); + const counter = store.useStore((state) => state.getValue(store.tables.CounterTable, {})); return ( <>
Counter: {counter?.value ?? "unset"}
-
{isConnected ? : <>}
+
{walletClient && chain && chain!.id === networkConfig.chainId && }
); }; -const useWorldContract = () => { - const networkConfig = useNetworkConfig(); - const publicClient = usePublicClient(); - const { data: walletClient } = useWalletClient(); - - const worldContract = getWorldContract(networkConfig.worldAddress, publicClient, walletClient!); - - return { worldContract, networkConfig, publicClient }; -}; - -const Incrementer = () => { +const Connected = () => { + const store = useStore(); const { - worldContract: { worldContract }, + worldContract: { worldContract, write$ }, + publicClient, + walletClient, } = useWorldContract(); + useEffect(() => { + if (import.meta.env.DEV) { + import("@latticexyz/dev-tools").then(({ mount }) => + mount({ + config: mudConfig, + publicClient: publicClient, + walletClient: walletClient, + latestBlock$: store.latestBlock$, + storedBlockLogs$: store.storedBlockLogs$, + worldAddress: worldContract.address, + worldAbi: worldContract.abi, + write$: write$.asObservable().pipe(share()), + useStore: store.useStore, + }) + ); + } + }, [walletClient.account.address]); + return ( ))} @@ -143,3 +112,35 @@ export function Connect() { ); } + +export function Wallet() { + const { chain } = useNetwork(); + const { chains, error, isLoading, pendingChainId, switchNetwork } = useSwitchNetwork(); + const { address } = useAccount(); + + const otherChains = chains.filter((x) => x.id !== chain?.id); + + return ( +
+
{address}
+
+ Connected to {chain?.name ?? chain?.id} + {chain?.unsupported && " (unsupported)"} +
+
+ {switchNetwork && otherChains.length && ( +
+ Switch to:{" "} + {otherChains.map((x) => ( + + ))} +
+ )} + +
{error?.message}
+
+ ); +} diff --git a/examples/minimal/packages/client-react-external-wallet/src/MUDContext.tsx b/examples/minimal/packages/client-react-external-wallet/src/MUDContext.tsx deleted file mode 100644 index ea6d3ed28a..0000000000 --- a/examples/minimal/packages/client-react-external-wallet/src/MUDContext.tsx +++ /dev/null @@ -1,23 +0,0 @@ -import { createContext, type ReactNode, useContext } from "react"; -import { type NetworkConfig } from "./mud/networkConfig"; - -type MUDConfig = { networkConfig: NetworkConfig }; - -const MUDContext = createContext(null); - -type Props = { - children: ReactNode; - value: MUDConfig; -}; - -export const MUDProvider = ({ children, value }: Props) => { - const currentValue = useContext(MUDContext); - if (currentValue) throw new Error("MUDProvider can only be used once"); - return {children}; -}; - -export const useMUD = () => { - const value = useContext(MUDContext); - if (!value) throw new Error("Must be used within a MUDProvider"); - return value; -}; diff --git a/examples/minimal/packages/client-react-external-wallet/src/mud/getWagmiConfig.ts b/examples/minimal/packages/client-react-external-wallet/src/mud/getWagmiConfig.ts index e2a525ee68..60230957ab 100644 --- a/examples/minimal/packages/client-react-external-wallet/src/mud/getWagmiConfig.ts +++ b/examples/minimal/packages/client-react-external-wallet/src/mud/getWagmiConfig.ts @@ -1,5 +1,6 @@ import { createPublicClient, fallback, webSocket, http, type ClientConfig } from "viem"; import { configureChains, createConfig } from "wagmi"; +import { publicProvider } from "wagmi/providers/public"; import { InjectedConnector } from "wagmi/connectors/injected"; import { transportObserver } from "@latticexyz/common"; import { type MUDChain } from "@latticexyz/common/chains"; @@ -13,7 +14,7 @@ export function getWagmiConfig(chain: MUDChain) { const publicClient = createPublicClient(clientOptions); - const { chains } = configureChains([chain], []); + const { chains } = configureChains([chain], [publicProvider()]); const wagmiConfig = createConfig({ autoConnect: true, diff --git a/examples/minimal/packages/client-react-external-wallet/src/mud/networkConfig.tsx b/examples/minimal/packages/client-react-external-wallet/src/mud/networkConfig.tsx index c47c5e224b..d26d6fc000 100644 --- a/examples/minimal/packages/client-react-external-wallet/src/mud/networkConfig.tsx +++ b/examples/minimal/packages/client-react-external-wallet/src/mud/networkConfig.tsx @@ -1,7 +1,11 @@ import { createContext, type ReactNode, useContext } from "react"; import { type Hex } from "viem"; -import worlds from "contracts/worlds.json"; +import { usePublicClient, useWalletClient, type WalletClient, type PublicClient } from "wagmi"; +import { Subject } from "rxjs"; +import { type ContractWrite, getContract } from "@latticexyz/common"; import { supportedChains } from "./supportedChains"; +import worlds from "contracts/worlds.json"; +import IWorldAbi from "contracts/out/IWorld.sol/IWorld.abi.json"; export type NetworkConfig = ReturnType; @@ -50,3 +54,30 @@ export const useNetworkConfig = () => { if (!value) throw new Error("Must be used within a NetworkConfigProvider"); return value; }; + +const getWorldContract = (address: Hex, publicClient: PublicClient, walletClient: WalletClient) => { + const write$ = new Subject(); + const worldContract = getContract({ + address, + abi: IWorldAbi, + publicClient, + walletClient, + onWrite: (write) => write$.next(write), + }); + + return { worldContract, write$ }; +}; + +export const useWorldContract = () => { + const networkConfig = useNetworkConfig(); + const publicClient = usePublicClient(); + const { data: walletClient } = useWalletClient(); + + if (!walletClient) { + throw new Error("useWorldContract is used incorrectly"); + } + + const worldContract = getWorldContract(networkConfig.worldAddress, publicClient, walletClient); + + return { worldContract, networkConfig, publicClient, walletClient }; +}; diff --git a/examples/minimal/packages/client-react-external-wallet/src/mud/store.tsx b/examples/minimal/packages/client-react-external-wallet/src/mud/store.tsx new file mode 100644 index 0000000000..7058fe5b36 --- /dev/null +++ b/examples/minimal/packages/client-react-external-wallet/src/mud/store.tsx @@ -0,0 +1,37 @@ +import { createContext, type ReactNode, useContext } from "react"; +import { type PublicClient } from "wagmi"; +import { syncToZustand } from "@latticexyz/store-sync/zustand"; +import { type NetworkConfig } from "./networkConfig"; +import mudConfig from "contracts/mud.config"; + +export type Store = Awaited>; + +export const syncStore = async (networkConfig: NetworkConfig, publicClient: PublicClient) => { + const { tables, useStore, latestBlock$, storedBlockLogs$, waitForTransaction } = await syncToZustand({ + config: mudConfig, + address: networkConfig.worldAddress, + publicClient, + startBlock: BigInt(networkConfig.initialBlockNumber), + }); + + return { tables, useStore, latestBlock$, storedBlockLogs$, waitForTransaction }; +}; + +const StoreContext = createContext(null); + +type Props = { + children: ReactNode; + store: Store; +}; + +export const StoreProvider = ({ children, store }: Props) => { + const currentValue = useContext(StoreContext); + if (currentValue) throw new Error("StoreProvider can only be used once"); + return {children}; +}; + +export const useStore = () => { + const value = useContext(StoreContext); + if (!value) throw new Error("Must be used within a StoreProvider"); + return value; +};