..and tap "Launch" to open your app.
If you watch your dev server and ngrok logs, you'll see a request to your server. But nothing will load until we signal to Warpcast that our app is `ready()`.
### Calling `ready()`
To give frames a consistent loading experience, clients display a splash screen and image until the app calls `sdk.actions.ready()`. In order to make it more visible here, let's add a splash image and loading color:
Now we get a nice background color and splash image:
Let's call `ready()` to load our app. We'll call `sdk.actions.ready()` in an effect on render, which tells the parent Farcaster app that our frame is ready to render and hides the splash screen:
```tsx
import { useEffect, useState } from "react";
import sdk from "@farcaster/frame-sdk";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
useEffect(() => {
const load = async () => {
sdk.actions.ready();
};
if (sdk && !isSDKLoaded) {
setIsSDKLoaded(true);
load();
}
}, [isSDKLoaded]);
return (
### Viewing context
When your frame loads, the parent Farcaster app provides it with context information, including the current user. Let's take a look at it.
We can access the context data at `sdk.context` to see information about the current user.:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState
{JSON.stringify(context, null, 2)}
{JSON.stringify(context, null, 2)}
### Invoking actions
Now let's make our frame do something. We can invoke actions by calling the functions on `sdk.actions`. We've already used `sdk.actions.ready`. We can also call functions like `sdk.actions.openUrl` and `sdk.actions.close` to send commands back to the Farcaster client app.
Let's start by opening an external URL. Add an `openUrl` callback that calls `sdk.actions.openUrl` and a button that calls it:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState
sdk.actions.openUrl
Tap the button and you'll be directed to an external URL.
Let's add another button to call `close()`:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState
sdk.actions.openUrl
sdk.actions.close
When you tap this, the frame should close.
### Wallet interactions
Finally, let's interact with the user's connected wallet. To do so, we can use the wallet connector and Wagmi hooks we set up earlier. To start, let's read the user's connected wallet address, using `useAccount`:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
import { useAccount } from "wagmi";
import { Button } from "~/components/ui/Button";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState{address}
If your wallet is connected to Warpcast, you should see its address. In case it's not, let's add a connect/disconnect button. Note that we'll need to import our Wagmi config to `connect`:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
import { useAccount } from "wagmi";
import { config } from "~/components/providers/WagmiProvider";
import { Button } from "~/components/ui/Button";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState{address}
{address}
Tap "Send Transaction" and you'll be directed to your wallet.
### Signatures
Finally, let's add two new helpers for wallet signature methods. Below is the full `Demo` component:
```tsx
import { useEffect, useCallback, useState } from "react";
import sdk, { type FrameContext } from "@farcaster/frame-sdk";
import {
useAccount,
useSendTransaction,
useSignMessage,
useSignTypedData,
useWaitForTransactionReceipt,
useDisconnect,
useConnect,
} from "wagmi";
import { config } from "~/components/providers/WagmiProvider";
import { Button } from "~/components/ui/Button";
import { truncateAddress } from "~/lib/truncateAddress";
export default function Demo() {
const [isSDKLoaded, setIsSDKLoaded] = useState(false);
const [context, setContext] = useState
{JSON.stringify(context, null, 2)}
sdk.actions.openUrl
sdk.actions.close
{truncateAddress(address)}