add chain switching example

This commit is contained in:
horsefacts 2024-12-03 19:57:23 -05:00 committed by lucas-neynar
parent 407bc837b2
commit ddcd3981fc
No known key found for this signature in database
2 changed files with 51 additions and 60 deletions

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import { useEffect, useCallback, useState } from "react"; import { useEffect, useCallback, useState, useMemo } from "react";
import sdk, { import sdk, {
FrameNotificationDetails, FrameNotificationDetails,
type FrameContext, type FrameContext,
@ -20,7 +20,7 @@ import {
import { config } from "~/components/providers/WagmiProvider"; import { config } from "~/components/providers/WagmiProvider";
import { Button } from "~/components/ui/Button"; import { Button } from "~/components/ui/Button";
import { truncateAddress } from "~/lib/truncateAddress"; import { truncateAddress } from "~/lib/truncateAddress";
import { base } from "wagmi/chains"; import { base, optimism } from "wagmi/chains";
export default function Demo( export default function Demo(
{ title }: { title?: string } = { title: "Frames v2 Demo" } { title }: { title?: string } = { title: "Frames v2 Demo" }
@ -59,6 +59,17 @@ export default function Demo(
const { disconnect } = useDisconnect(); const { disconnect } = useDisconnect();
const { connect } = useConnect(); const { connect } = useConnect();
const {
switchChain,
error: switchChainError,
isError: isSwitchChainError,
isPending: isSwitchChainPending,
} = useSwitchChain();
const handleSwitchChain = useCallback(() => {
switchChain({ chainId: chainId === base.id ? optimism.id : base.id });
}, [switchChain, chainId]);
useEffect(() => { useEffect(() => {
const load = async () => { const load = async () => {
setContext(await sdk.context); setContext(await sdk.context);
@ -139,6 +150,7 @@ export default function Demo(
const sendTx = useCallback(() => { const sendTx = useCallback(() => {
sendTransaction( sendTransaction(
{ {
// call yoink() on Yoink contract
to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878", to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878",
data: "0x9846cd9efc000023c0", data: "0x9846cd9efc000023c0",
}, },
@ -155,7 +167,7 @@ export default function Demo(
domain: { domain: {
name: "Frames v2 Demo", name: "Frames v2 Demo",
version: "1", version: "1",
chainId: 8453, chainId,
}, },
types: { types: {
Message: [{ name: "content", type: "string" }], Message: [{ name: "content", type: "string" }],
@ -165,7 +177,7 @@ export default function Demo(
}, },
primaryType: "Message", primaryType: "Message",
}); });
}, [signTypedData]); }, [chainId, signTypedData]);
const toggleContext = useCallback(() => { const toggleContext = useCallback(() => {
setIsContextOpen((prev) => !prev); setIsContextOpen((prev) => !prev);
@ -278,7 +290,7 @@ export default function Demo(
{chainId && ( {chainId && (
<div className="my-2 text-xs"> <div className="my-2 text-xs">
Chain ID: <pre className="inline">{chainId}</pre> Chain ID: <pre className="inline">{chainId}</pre>
</div> </div>
)} )}
@ -293,7 +305,7 @@ export default function Demo(
{isConnected ? "Disconnect" : "Connect"} {isConnected ? "Disconnect" : "Connect"}
</Button> </Button>
</div> </div>
<div className="mb-4"> <div className="mb-4">
<SignMessage /> <SignMessage />
</div> </div>
@ -337,7 +349,14 @@ export default function Demo(
{isSignTypedError && renderError(signTypedError)} {isSignTypedError && renderError(signTypedError)}
</div> </div>
<div className="mb-4"> <div className="mb-4">
<SwitchChain /> <Button
onClick={handleSwitchChain}
disabled={isSwitchChainPending}
isLoading={isSwitchChainPending}
>
Switch to {chainId === base.id ? "Optimism" : "Base"}
</Button>
{isSwitchChainError && renderError(switchChainError)}
</div> </div>
</> </>
)} )}
@ -346,34 +365,6 @@ export default function Demo(
); );
} }
function SwitchChain() {
const chainId = useChainId();
const {
switchChain,
error: switchChainError,
isError: isSwitchChainError,
isPending: isSwitchChainPending,
} = useSwitchChain();
const handleSwitchChain = useCallback(() => {
switchChain({ chainId: chainId === 1 ? 8453 : 1 });
}, [switchChain, chainId]);
return (
<>
<Button
onClick={handleSwitchChain}
disabled={isSwitchChainPending}
isLoading={isSwitchChainPending}
>
Switch chain
</Button>
{isSwitchChainError && renderError(switchChainError)}
</>
);
}
function SignMessage() { function SignMessage() {
const { isConnected } = useAccount(); const { isConnected } = useAccount();
const { connectAsync } = useConnect(); const { connectAsync } = useConnect();
@ -387,16 +378,15 @@ function SignMessage() {
const handleSignMessage = useCallback(async () => { const handleSignMessage = useCallback(async () => {
if (!isConnected) { if (!isConnected) {
await connectAsync({ await connectAsync({
chainId: base.id, chainId: base.id,
connector: config.connectors[0] connector: config.connectors[0],
}) });
} }
signMessage({ message: "Hello from Frames v2!" }); signMessage({ message: "Hello from Frames v2!" });
}, [connectAsync, isConnected, signMessage]); }, [connectAsync, isConnected, signMessage]);
return ( return (
<> <>
<Button <Button
@ -417,7 +407,7 @@ function SignMessage() {
} }
function SendEth() { function SendEth() {
const { isConnected } = useAccount(); const { isConnected, chainId } = useAccount();
const { const {
sendTransaction, sendTransaction,
data, data,
@ -428,17 +418,22 @@ function SendEth() {
const { isLoading: isConfirming, isSuccess: isConfirmed } = const { isLoading: isConfirming, isSuccess: isConfirmed } =
useWaitForTransactionReceipt({ useWaitForTransactionReceipt({
hash: data hash: data,
}); });
const toAddr = useMemo(() => {
// Protocol guild address
return chainId === base.id
? "0x32e3C7fD24e175701A35c224f2238d18439C7dBC"
: "0xB3d8d7887693a9852734b4D25e9C0Bb35Ba8a830";
}, [chainId]);
const handleSend = useCallback(() => { const handleSend = useCallback(() => {
sendTransaction( sendTransaction({
{ to: toAddr,
to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878", value: 1n,
value: 1n, });
} }, [toAddr, sendTransaction]);
);
}, [sendTransaction]);
return ( return (
<> <>
@ -467,10 +462,7 @@ function SendEth() {
); );
} }
const renderError = (error: Error | null) => {
const renderError = (error: Error | null) => { if (!error) return null;
if (!error) return null; return <div className="text-red-500 text-xs mt-1">{error.message}</div>;
return <div className="text-red-500 text-xs mt-1">{error.message}</div>; };
};

View File

@ -1,14 +1,13 @@
import { createConfig, http, WagmiProvider } from "wagmi"; import { createConfig, http, WagmiProvider } from "wagmi";
import { base, mainnet } from "wagmi/chains"; import { base, optimism } from "wagmi/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { frameConnector } from "~/lib/connector"; import { frameConnector } from "~/lib/connector";
export const config = createConfig({ export const config = createConfig({
chains: [base, mainnet], chains: [base, optimism],
transports: { transports: {
// Configure dedicated RPC providers when using in production
[base.id]: http(), [base.id]: http(),
[mainnet.id]: http(), [optimism.id]: http(),
}, },
connectors: [frameConnector()], connectors: [frameConnector()],
}); });