FarHack
Welcome to the ultimate Farcaster hackathon to learn how to build innovative Frames and Bots with XMTP. Happy coding 🫡

Prizes 🏆
🤖 Best use of an XMTP Bot with Farcaster - $500
This prize goes to the team that most effectively creates a Bot that uses Farcaster in a meaningful way.
Requirements:
Develop a Farcaster Bot using XMTP libraries
To create a new XMTP bot using BotKit cli tool:
npx create-xmtp-bot <bot-name>
cd <bot-name>
This is a code example of a bot that replies gm :
import { run, HandlerContext } from "@xmtp/botkit";
run(async (context: HandlerContext) => {
  // Get the message and the address from the sender
  const { content, senderAddress } = context.message;
  // Read or write to Farcaster
  // To reply, just call `reply` on the HandlerContext.
  await context.reply("gm");
});
Resources
- BotKit: Tooling for creating bots with XMTP.
 - Tutorial: Learn how to build and deploy a bot.
 - Conversational: Drive retention with conversations and subscriptions.
 - GPT: Relay messages through Open AI APIs.
 
🖼️ Best Chat Frame - $500
This prize goes to the best Frame compatible with messaging apps.
Requirements:
Integrate your Frame with XMTP
Metadata
In compliance with Open Frames, Use a meta tag in your frame's HTML to declare the client protocols your frame supports.
<meta property="of:accepts:xmtp" content="vNext" />
Validate incoming messages
Implement message validation using @xmtp/frames-validator to ensure the authenticity of incoming POST requests.
import { validateFramesPost } from "@xmtp/frames-validator";
export function handler(requestBody: any) {
  if (requestBody.clientProtocol.startsWith("xmtp")) {
    const { verifiedWalletAddress } = await validateFramesPost(requestBody);
    // Handle verified XMTP payload
  } else {
    // Handle Farcaster or other protocol payloads
  }
}
Frameworks
Popular frameworks have already integrated Open Frames into their stacks:
OnChainKit
Discover how OnchainKit seamlessly incorporates XMTP payloads
Metadata:
const frameMetadata = getFrameMetadata({
  /**
   * Frame metadata like Image, Buttons, Input, etc.
   */
  isOpenFrame: true,
  accepts: { xmtp: "vNext" },
});
export const metadata: Metadata = {
  /**
   * ...other metadata
   */
  other: {
    ...frameMetadata,
  },
};
Validate incoming messages
import {
  isXmtpFrameRequest,
  getXmtpFrameMessage,
} from "@coinbase/onchainkit/xmtp";
/* ... */
async function getResponse(req: any): Promise<NextResponse> {
  const body: FrameRequest = await req.json();
  if (isXmtpFrameRequest(body)) {
    const { isValid, message } = await getXmtpFrameMessage(body);
    // ... do something with the message if isValid is true
    if (isValid) {
      const { verifiedWalletAddress } = message;
      // ... do something with the verifiedWalletAddress
    }
  } else {
    // ...
  }
}
- OnChainKit: Official OnchainKit documentation.
 - Quickstart: OnchainKit quickstart that integrates XMTP.
 
Frames.js
Learn more about the integration of XMTP payloads within FrameJS
Metadata
const acceptedProtocols: ClientProtocolId[] = [
  {
    id: "xmtp",
    version: "vNext",
  },
  {
    id: "farcaster",
    version: "vNext",
  },
];
Validate incoming messages:
let fid: number | undefined;
let walletAddress: string | undefined;
import {
  isXmtpFrameRequest,
  getXmtpFrameMessage,
} from "@coinbase/onchainkit/xmtp";
import { NextResponse } from "next/server";
import type { FrameRequest } from "@coinbase/onchainkit";
async function getResponse(req: any): Promise<NextResponse> {
  const body: FrameRequest = await req.json();
  if (isXmtpFrameRequest(body)) {
    const { isValid, message } = await getXmtpFrameMessage(body);
    walletAddress = frameMessage?.verifiedWalletAddress;
  } else {
    // ...
  }
}
- Frames.js: Official Framesjs Documentation.
 - Quickstart: Onchainkit quickstart that integrates XMTP.
 
Frog
- Frog: There is an active discussion to integrate Open Frames.
 
- Send your Frame through Converse to 
hi.xmtp.eth. 
🔔 Best Use of XMTP to Send Notifications - $500
Implement a Frame or Bot that sends notifications through XMTP.
Requirements:
Send notifications using XMTP libraries
Install the js sdk:
yarn add @xmtp/xmtp-js ethers
Send notification:
import { Wallet } from "ethers";
import { Client } from "@xmtp/xmtp-js";
// Function to send a broadcast message to a list of recipients
async function sendNotification(recipient, message) {
  // In a real application, use your wallet
  const signer = new Wallet("private key");
  const xmtp = await Client.create(signer);
  // Check if the recipient is activated on the XMTP network
  if (await xmtp.canMessage(recipient)) {
    const conversation = await xmtp.conversations.newConversation(recipient);
    await conversation.send(message);
    console.log(`Message successfully sent to ${recipient}`);
  } else {
    console.log(`Recipient ${recipient} is not activated on the XMTP network.`);
  }
}
// Example usage
sendNotification("Hello from Farcaster!", "0x123...");
Messaging apps 💬
Test the bots in messaging apps
- Converse: Own your conversations. Works with Frames (Frame Transactions TBA).
 - Coinbase Wallet: Your key to the world of crypto. (Frame support TBA).
 - dev-inbox: Web messaging client (Frame Transactions TBA).
 
Identities 🥷🏻
Learn about the 2 million identities part of XMTP by visiting the Dune dashboard.
Examples 🔥
See live examples in the Awesome XMTP ⭐️ repo.