From 2bbf813e206665c69f1382a9161d707c8c37a34b Mon Sep 17 00:00:00 2001 From: horsefacts Date: Sat, 23 Nov 2024 23:55:52 -0500 Subject: [PATCH] add signatures --- src/components/Demo.tsx | 116 ++++++++++++++++++++++++++++++++--- src/components/ui/Button.tsx | 11 +++- 2 files changed, 118 insertions(+), 9 deletions(-) diff --git a/src/components/Demo.tsx b/src/components/Demo.tsx index 427cbd5..7dd0577 100644 --- a/src/components/Demo.tsx +++ b/src/components/Demo.tsx @@ -1,6 +1,12 @@ import { useEffect, useCallback, useState } from "react"; import sdk, { type FrameContext } from "@farcaster/frame-sdk"; -import { useAccount, useSendTransaction } from "wagmi"; +import { + useAccount, + useSendTransaction, + useSignMessage, + useSignTypedData, + useWaitForTransactionReceipt, +} from "wagmi"; import { Button } from "~/components/ui/Button"; import { truncateAddress } from "~/lib/truncateAddress"; @@ -9,9 +15,34 @@ 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 } = useSendTransaction(); + 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 () => { @@ -33,16 +64,49 @@ export default function Demo() { }, []); const sendTx = useCallback(() => { - sendTransaction({ - to: "0x4bBFD120d9f352A0BEd7a014bd67913a2007a878", - data: "0x9846cd9efc000023c0", - }); + 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...
; } @@ -110,9 +174,47 @@ export default function Demo() { {isConnected && ( <>
- + {isSendTxError && renderError(sendTxError)} + {txHash && ( +
+
Hash: {truncateAddress(txHash)}
+
+ Status:{" "} + {isConfirming + ? "Confirming..." + : isConfirmed + ? "Confirmed!" + : "Pending"} +
+
+ )} +
+
+ + {isSignError && renderError(signError)} +
+
+ + {isSignTypedError && renderError(signTypedError)}
)} diff --git a/src/components/ui/Button.tsx b/src/components/ui/Button.tsx index 3e2c0ed..51d1553 100644 --- a/src/components/ui/Button.tsx +++ b/src/components/ui/Button.tsx @@ -1,14 +1,21 @@ interface ButtonProps extends React.ButtonHTMLAttributes { children: React.ReactNode; + isLoading?: boolean; } -export function Button({ children, className = "", ...props }: ButtonProps) { +export function Button({ children, className = "", isLoading = false, ...props }: ButtonProps) { return ( ); }