mirror of
https://github.com/neynarxyz/create-farcaster-mini-app.git
synced 2025-12-11 11:52:35 -05:00
93 lines
2.7 KiB
TypeScript
93 lines
2.7 KiB
TypeScript
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 });
|
|
}
|