Skip to main content

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
  • 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.

Was the information on this page helpful?
powered by XMTP