mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-11-15 23:58:56 -05:00
add signatures
This commit is contained in:
parent
33eea440b3
commit
2bbf813e20
@ -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<FrameContext>();
|
||||
const [isContextOpen, setIsContextOpen] = useState(false);
|
||||
const [txHash, setTxHash] = useState<string | null>(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 <div className="text-red-500 text-xs mt-1">{error.message}</div>;
|
||||
};
|
||||
|
||||
if (!isSDKLoaded) {
|
||||
return <div>Loading...</div>;
|
||||
}
|
||||
@ -110,9 +174,47 @@ export default function Demo() {
|
||||
{isConnected && (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<Button onClick={sendTx} disabled={!isConnected}>
|
||||
<Button
|
||||
onClick={sendTx}
|
||||
disabled={!isConnected || isSendTxPending}
|
||||
isLoading={isSendTxPending}
|
||||
>
|
||||
Send Transaction
|
||||
</Button>
|
||||
{isSendTxError && renderError(sendTxError)}
|
||||
{txHash && (
|
||||
<div className="mt-2 text-xs">
|
||||
<div>Hash: {truncateAddress(txHash)}</div>
|
||||
<div>
|
||||
Status:{" "}
|
||||
{isConfirming
|
||||
? "Confirming..."
|
||||
: isConfirmed
|
||||
? "Confirmed!"
|
||||
: "Pending"}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
onClick={sign}
|
||||
disabled={!isConnected || isSignPending}
|
||||
isLoading={isSignPending}
|
||||
>
|
||||
Sign Message
|
||||
</Button>
|
||||
{isSignError && renderError(signError)}
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<Button
|
||||
onClick={signTyped}
|
||||
disabled={!isConnected || isSignTypedPending}
|
||||
isLoading={isSignTypedPending}
|
||||
>
|
||||
Sign Typed Data
|
||||
</Button>
|
||||
{isSignTypedError && renderError(signTypedError)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
@ -1,14 +1,21 @@
|
||||
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
|
||||
children: React.ReactNode;
|
||||
isLoading?: boolean;
|
||||
}
|
||||
|
||||
export function Button({ children, className = "", ...props }: ButtonProps) {
|
||||
export function Button({ children, className = "", isLoading = false, ...props }: ButtonProps) {
|
||||
return (
|
||||
<button
|
||||
className={`w-full max-w-xs mx-auto block bg-[#7C65C1] text-white py-3 px-6 rounded-lg transition-colors disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:bg-[#7C65C1] hover:bg-[#6952A3] ${className}`}
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
{isLoading ? (
|
||||
<div className="flex items-center justify-center">
|
||||
<div className="animate-spin h-5 w-5 border-2 border-white border-t-transparent rounded-full" />
|
||||
</div>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</button>
|
||||
);
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user