import { NextRequest } from 'next/server'; import { ParseWebhookEvent, parseWebhookEvent, verifyAppKeyWithNeynar, } from '@farcaster/miniapp-node'; import { APP_NAME } from '~/lib/constants'; import { deleteUserNotificationDetails, setUserNotificationDetails, } from '~/lib/kv'; import { sendMiniAppNotification } from '~/lib/notifs'; export async function POST(request: NextRequest) { // If Neynar is enabled, we don't need to handle webhooks here // as they will be handled by Neynar's webhook endpoint const neynarEnabled = process.env.NEYNAR_API_KEY && process.env.NEYNAR_CLIENT_ID; if (neynarEnabled) { return Response.json({ success: true }); } const requestJson = await request.json(); let data; try { data = await parseWebhookEvent(requestJson, verifyAppKeyWithNeynar); } catch (e: unknown) { const error = e as ParseWebhookEvent.ErrorType; switch (error.name) { case 'VerifyJsonFarcasterSignature.InvalidDataError': case 'VerifyJsonFarcasterSignature.InvalidEventDataError': // The request data is invalid return Response.json( { success: false, error: error.message }, { status: 400 }, ); case 'VerifyJsonFarcasterSignature.InvalidAppKeyError': // The app key is invalid return Response.json( { success: false, error: error.message }, { status: 401 }, ); case 'VerifyJsonFarcasterSignature.VerifyAppKeyError': // Internal error verifying the app key (caller may want to try again) return Response.json( { success: false, error: error.message }, { status: 500 }, ); } } const fid = data.fid; const event = data.event; // Only handle notifications if Neynar is not enabled // When Neynar is enabled, notifications are handled through their webhook switch (event.event) { case 'frame_added': if (event.notificationDetails) { await setUserNotificationDetails(fid, event.notificationDetails); await sendMiniAppNotification({ fid, title: `Welcome to ${APP_NAME}`, body: 'Mini app is now added to your client', }); } else { await deleteUserNotificationDetails(fid); } break; case 'frame_removed': await deleteUserNotificationDetails(fid); break; case 'notifications_enabled': await setUserNotificationDetails(fid, event.notificationDetails); await sendMiniAppNotification({ fid, title: `Welcome to ${APP_NAME}`, body: 'Notifications are now enabled', }); break; case 'notifications_disabled': await deleteUserNotificationDetails(fid); break; } return Response.json({ success: true }); }