add initial demo app

This commit is contained in:
horsefacts
2024-11-23 23:19:40 -05:00
committed by lucas-neynar
parent 5143ab4ce4
commit 33eea440b3
22 changed files with 5723 additions and 0 deletions

19
src/components/App.tsx Normal file
View File

@@ -0,0 +1,19 @@
"use client";
import dynamic from "next/dynamic";
const Demo = dynamic(() => import("./Demo"), {
ssr: false,
});
const WagmiConfig = dynamic(() => import("./WagmiProvider"), {
ssr: false,
});
export function App() {
return (
<WagmiConfig>
<Demo />
</WagmiConfig>
);
}

122
src/components/Demo.tsx Normal file
View File

@@ -0,0 +1,122 @@
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
import { useAccount, useSendTransaction } 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<FrameContext>();
const [isContextOpen, setIsContextOpen] = useState(false);
const { address, isConnected } = useAccount();
const { sendTransaction } = useSendTransaction();
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",
});
}, [sendTransaction]);
const toggleContext = useCallback(() => {
setIsContextOpen((prev) => !prev);
}, []);
if (!isSDKLoaded) {
return <div>Loading...</div>;
}
return (
<div className="w-[300px] mx-auto py-4 px-2">
<h1 className="text-2xl font-bold text-center mb-4">Frames v2 Demo</h1>
<div className="mb-4">
<h2 className="font-2xl font-bold">Context</h2>
<button
onClick={toggleContext}
className="flex items-center gap-2 transition-colors"
>
<span
className={`transform transition-transform ${
isContextOpen ? "rotate-90" : ""
}`}
>
</span>
Tap to expand
</button>
{isContextOpen && (
<div className="p-4 mt-2 bg-gray-100 dark:bg-gray-800 rounded-lg">
<pre className="font-mono text-xs whitespace-pre-wrap break-words max-w-[260px] overflow-x-">
{JSON.stringify(context, null, 2)}
</pre>
</div>
)}
</div>
<div>
<h2 className="font-2xl font-bold">Actions</h2>
<div className="mb-4">
<div className="p-2 bg-gray-100 dark:bg-gray-800 rounded-lg my-2">
<pre className="font-mono text-xs whitespace-pre-wrap break-words max-w-[260px] overflow-x-">
sdk.actions.openUrl
</pre>
</div>
<Button onClick={openUrl}>Open Link</Button>
</div>
<div className="mb-4">
<div className="p-2 bg-gray-100 dark:bg-gray-800 rounded-lg my-2">
<pre className="font-mono text-xs whitespace-pre-wrap break-words max-w-[260px] overflow-x-">
sdk.actions.close
</pre>
</div>
<Button onClick={close}>Close Frame</Button>
</div>
</div>
<div>
<h2 className="font-2xl font-bold">Wallet</h2>
{address && (
<div className="my-2 text-xs">
Address: <pre className="inline">{truncateAddress(address)}</pre>
</div>
)}
{isConnected && (
<>
<div className="mb-4">
<Button onClick={sendTx} disabled={!isConnected}>
Send Transaction
</Button>
</div>
</>
)}
</div>
</div>
);
}

View File

@@ -0,0 +1,22 @@
import { createConfig, http, WagmiProvider } from "wagmi";
import { base } from "wagmi/chains";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { frameConnector } from "~/lib/connector";
export const config = createConfig({
chains: [base],
transports: {
[base.id]: http(),
},
connectors: [frameConnector()],
});
const queryClient = new QueryClient();
export default function WagmiConfig({ children }: { children: React.ReactNode }) {
return (
<WagmiProvider config={config}>
<QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
</WagmiProvider>
);
}

View File

@@ -0,0 +1,14 @@
interface ButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
children: React.ReactNode;
}
export function Button({ children, className = "", ...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}
</button>
);
}