import { useEffect, useCallback, useState } from "react"; import sdk, { type FrameContext } from "@farcaster/frame-sdk"; import { useAccount, useSendTransaction, useSignMessage, useSignTypedData, useWaitForTransactionReceipt, } from "wagmi"; import { Button } from "~/components/ui/Button"; import { truncateAddress } from "~/lib/truncateAddress"; export default function Demo() { const [isSDKLoaded, setIsSDKLoaded] = useState(false); const [context, setContext] = useState(); const [isContextOpen, setIsContextOpen] = useState(false); const [txHash, setTxHash] = useState(null); const { address, isConnected } = useAccount(); const { sendTransaction, error: sendTxError, isError: isSendTxError, isPending: isSendTxPending, } = useSendTransaction(); const { signMessage, error: signError, isError: isSignError, isPending: isSignPending, } = useSignMessage(); const { signTypedData, error: signTypedError, isError: isSignTypedError, isPending: isSignTypedPending, } = useSignTypedData(); const { isLoading: isConfirming, isSuccess: isConfirmed } = useWaitForTransactionReceipt({ hash: txHash as `0x${string}`, }); useEffect(() => { const load = async () => { setContext(await sdk.context); sdk.actions.ready(); }; if (sdk && !isSDKLoaded) { setIsSDKLoaded(true); load(); } }, [isSDKLoaded]); const openUrl = useCallback(() => { sdk.actions.openUrl("https://www.youtube.com/watch?v=dQw4w9WgXcQ"); }, []); const close = useCallback(() => { sdk.actions.close(); }, []); const sendTx = useCallback(() => { sendTransaction( { to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878", data: "0x9846cd9efc000023c0", }, { onSuccess: (hash) => { setTxHash(hash); }, } ); }, [sendTransaction]); const sign = useCallback(() => { signMessage({ message: "Hello from Frames v2!" }); }, [signMessage]); const signTyped = useCallback(() => { signTypedData({ domain: { name: "Frames v2 Demo", version: "1", chainId: 8453, }, types: { Message: [{ name: "content", type: "string" }], }, message: { content: "Hello from Frames v2!", }, primaryType: "Message", }); }, [signTypedData]); const toggleContext = useCallback(() => { setIsContextOpen((prev) => !prev); }, []); const renderError = (error: Error | null) => { if (!error) return null; return
{error.message}
; }; if (!isSDKLoaded) { return
Loading...
; } return (

Frames v2 Demo

Context

{isContextOpen && (
              {JSON.stringify(context, null, 2)}
            
)}

Actions

              sdk.actions.openUrl
            
              sdk.actions.close
            

Wallet

{address && (
Address:
{truncateAddress(address)}
)} {isConnected && ( <>
{isSendTxError && renderError(sendTxError)} {txHash && (
Hash: {truncateAddress(txHash)}
Status:{" "} {isConfirming ? "Confirming..." : isConfirmed ? "Confirmed!" : "Pending"}
)}
{isSignError && renderError(signError)}
{isSignTypedError && renderError(signTypedError)}
)}
); }