Create an invite frame to add users to a channel on Farcaster from a POAP event.
This project uses frog.fm in Nextjs to serve the farcaster channel invite frame, fetches POAP data from poap.tech, and finds Farcaster users using Neynar SDK. Created at Devcon 2024.
Uses cast-intent as WarpcastUrlBuilder to create frame cast in Farcaster channel.
Follow app logic in main.ts
4 env vars to add to your .env.local file:
POAP_EVENT_ID- the event id of the POAPNEYNAR_API_KEY- API key from NeynarPOAP_API_KEY- API key from poap.techWC_INVITE_LINK- channel invite link from Warpcast, must be generated by a user with moderator permissions for the channel, generate and add manually
-
Clone repository to local
-
Install dependencies using your preferred package manager - I use
pnpmnpm install # or pnpm install # or yarn install
-
Set up poap.tech and Neynar API keys
- Obtain API credentials for POAP.tech to query POAP wallet holders
- Obtain API credentials for Neynar to map wallet addresses to Farcaster IDs
- Add credentials to
.env.localfile
-
Replace POAP event ID and run
main.tsscript, it will:-
Fetch POAP wallets via poap.tech API -
GET event/{id}/poaps- Use the poap.tech API to retrieve array of wallet addresses holding a specific POAP
- implemented in
lib/poap-wallets.tsas@getPoapWallets
- implemented in
- Use the poap.tech API to retrieve array of wallet addresses holding a specific POAP
-
Resolve Farcaster IDs using POAP wallets via Neynar SDK -
GET /v2/farcaster/user/bulk-by-address- Use the Neynar SDK/API to map the fetched wallets to Farcaster user profiles
- implemented in
lib/get-fids.tsas@getFids
- implemented in
- Use the Neynar SDK/API to map the fetched wallets to Farcaster user profiles
-
Output the resolved Farcaster IDs to JSON:
returned-user-fids.json
Use the
_verbose: trueoption to see the intermediate data and output each step to a separate file -
-
Create and Deliver Invites
- Build the invite flow using the repository's utilities and APIs:
- Generate an Allowlist: Compile Farcaster IDs eligible for channel invites.
- implemented in
lib/get-fids.tsas@processForFids
- implemented in
- Deliver Invites: Use Farcaster frames or direct messages to send invites to Farcaster users.
- Generate an Allowlist: Compile Farcaster IDs eligible for channel invites.
- Build the invite flow using the repository's utilities and APIs:
-
Customize Farcaster Frame
- Customize the frame at
app/api/[[...routes]]/route.tsx- uses frog.fm as framework for frames - Run dev server
npm run dev # or pnpm dev- Head to http://localhost:3000/api/dev to inspect frame using frog.fm devtools
- Customize and repeat until satisfied
- Customize the frame at
-
Customize the Announcement Cast in
cast.ts- replace the options properties in the
@WarpcastUrlBuilder.composerUrlmethod calloptions.text- the text of the cast delivering the frame invitesoptions.embeds- url of the live frame server api routeoptions.channelKey- the name of the channel to cast the frame in
// example const url = warpcastUrlBuilder.composerUrl({ text: `Welcome new frens! If you played a game and got a /poap from me at /devcon love to hear from you in /tabletop! Click Start to get your channel invite!`, embeds: ['https://poap-invites-frame.vercel.app/api'], channelKey: 'tabletop', }); // https://warpcast.com/~/compose?text=Welcome%2520new%2520frens%21%2520If%2520you%2520played%2520a%2520game%2520and%2520got%2520a%2520%252Fpoap%2520from%2520me%2520at%2520%252Fdevcon%2520love%2520to%2520hear%2520from%2520you%2520in%2520%252Ftabletop%21%2520%250A%2520%2520%2520%2520%250A%2520%2520%2520%2520Click%2520Start%2520to%2520get%2520your%2520channel%2520invite%21&embeds%5B%5D=https%3A%2F%2Fpoap-invites-frame.vercel.app%2Fapi&channelKey=tabletop
- replace the options properties in the
-
Deliver Invites via Frame Cast in Farcaster Channel
- run
cast.tsto create the composer URL -@composerUrl - click the composer URL in the console to cast the frame!
- run
The simplest way I've found to run single typescript files in Node is with ts-node dev dependency and the following command:
node --loader ts-node/esm file.tsNote: Requires "allowImportingTsExtensions": true and "noEmit": true in tsconfig.json
