Skip to content

Commit ddec3da

Browse files
committed
Refactor Farcaster frame validation (#5211)
1 parent ac78881 commit ddec3da

File tree

10 files changed

+49
-61
lines changed

10 files changed

+49
-61
lines changed

apps/dashboard/src/classes/CoinbaseKit.ts

Lines changed: 0 additions & 12 deletions
This file was deleted.
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import {
2+
type FrameRequest,
3+
type FrameValidationData,
4+
getFrameMessage,
5+
} from "@coinbase/onchainkit";
6+
7+
export function validateFrameMessage(body: FrameRequest) {
8+
return getFrameMessage(body, {
9+
neynarApiKey: process.env.NEYNAR_API_KEY,
10+
});
11+
}
12+
13+
export function getFarcasterAccountAddress(
14+
interactor: FrameValidationData["interactor"],
15+
) {
16+
// Get the first verified account or custody account if first verified account doesn't exist
17+
return interactor.verified_accounts[0] ?? interactor.custody_address;
18+
}

apps/dashboard/src/pages/api/frame/base/get-tx-frame.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import { getThirdwebClient } from "@/constants/thirdweb.server";
2-
import type { FrameRequest } from "@coinbase/onchainkit";
3-
import { CoinbaseKit } from "classes/CoinbaseKit";
2+
import {
3+
getFarcasterAccountAddress,
4+
validateFrameMessage,
5+
} from "lib/farcaster-frames";
46
import type { NextApiRequest, NextApiResponse } from "next";
57
import { getContract } from "thirdweb";
68
import { base } from "thirdweb/chains";
79
import { errorResponse } from "utils/api";
8-
import {
9-
getErc721PreparedEncodedData,
10-
getFarcasterAccountAddress,
11-
} from "utils/tx-frame";
10+
import { getErc721PreparedEncodedData } from "utils/tx-frame";
1211
import { abi } from "./abi";
1312

1413
// https://thirdweb.com/base/0x352810fF1c51a42B568662D46570A30B590a715a
@@ -24,9 +23,7 @@ export default async function handler(
2423
}
2524

2625
// Validate message with @coinbase/onchainkit
27-
const { isValid, message } = await CoinbaseKit.validateMessage(
28-
req.body as FrameRequest,
29-
);
26+
const { isValid, message } = await validateFrameMessage(req.body);
3027

3128
// Validate if message is valid
3229
if (!isValid || !message) {

apps/dashboard/src/pages/api/frame/connect.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import type { FrameRequest } from "@coinbase/onchainkit";
2-
import { CoinbaseKit } from "classes/CoinbaseKit";
31
import { ConnectFrame } from "classes/ConnectFrame";
2+
import {
3+
getFarcasterAccountAddress,
4+
validateFrameMessage,
5+
} from "lib/farcaster-frames";
46
import type { NextRequest } from "next/server";
57
import {
68
errorResponse,
79
redirectResponse,
810
successHtmlResponse,
911
} from "utils/api";
10-
import { getFarcasterAccountAddress } from "utils/farcaster";
1112

1213
export const config = {
1314
runtime: "edge",
@@ -18,9 +19,8 @@ export default async function handler(req: NextRequest) {
1819
return errorResponse("Invalid method", 400);
1920
}
2021

21-
const body = (await req.json()) as FrameRequest;
22-
23-
const { isValid, message } = await CoinbaseKit.validateMessage(body);
22+
const body = await req.json();
23+
const { isValid, message } = await validateFrameMessage(body);
2424

2525
if (!isValid || !message) {
2626
return errorResponse("Invalid message", 400);

apps/dashboard/src/pages/api/frame/degen/mint.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import { type FrameRequest, getFrameHtmlResponse } from "@coinbase/onchainkit";
2-
import { CoinbaseKit } from "classes/CoinbaseKit";
1+
import { getFrameHtmlResponse } from "@coinbase/onchainkit";
32
import { ThirdwebDegenEngine } from "classes/ThirdwebDegenEngine";
3+
import {
4+
getFarcasterAccountAddress,
5+
validateFrameMessage,
6+
} from "lib/farcaster-frames";
47
import { getAbsoluteUrl } from "lib/vercel-utils";
58
import type { NextRequest } from "next/server";
69
import {
710
errorResponse,
811
redirectResponse,
912
successHtmlResponse,
1013
} from "utils/api";
11-
import { getFarcasterAccountAddress } from "utils/farcaster";
1214
import { shortenAddress } from "utils/string";
1315

1416
const postUrl = `${getAbsoluteUrl()}/api/frame/degen/mint`;
@@ -26,9 +28,9 @@ export default async function handler(req: NextRequest) {
2628
return errorResponse("Invalid method", 400);
2729
}
2830

29-
const body = (await req.json()) as FrameRequest;
31+
const body = await req.json();
3032

31-
const { isValid, message } = await CoinbaseKit.validateMessage(body);
33+
const { isValid, message } = await validateFrameMessage(body);
3234

3335
if (!isValid || !message) {
3436
return errorResponse("Invalid message", 400);

apps/dashboard/src/pages/api/frame/engine.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import type { FrameRequest } from "@coinbase/onchainkit";
2-
import { CoinbaseKit } from "classes/CoinbaseKit";
31
import { ConnectFrame } from "classes/ConnectFrame";
2+
import {
3+
getFarcasterAccountAddress,
4+
validateFrameMessage,
5+
} from "lib/farcaster-frames";
46
import type { NextRequest } from "next/server";
57
import {
68
errorResponse,
79
redirectResponse,
810
successHtmlResponse,
911
} from "utils/api";
10-
import { getFarcasterAccountAddress } from "utils/farcaster";
1112

1213
export const config = {
1314
runtime: "edge",
@@ -18,9 +19,9 @@ export default async function handler(req: NextRequest) {
1819
return errorResponse("Invalid method", 400);
1920
}
2021

21-
const body = (await req.json()) as FrameRequest;
22+
const body = await req.json();
2223

23-
const { isValid, message } = await CoinbaseKit.validateMessage(body);
24+
const { isValid, message } = await validateFrameMessage(body);
2425

2526
if (!isValid || !message) {
2627
return errorResponse("Invalid message", 400);

apps/dashboard/src/pages/api/frame/superchain.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
import type { FrameRequest } from "@coinbase/onchainkit";
2-
import { CoinbaseKit } from "classes/CoinbaseKit";
31
import { SuperChainFrame } from "classes/SuperChainFrame";
2+
import { validateFrameMessage } from "lib/farcaster-frames";
43
import {
54
finalGrowthPlanFrameMetaData,
65
growthPlanFrameMetaData,
@@ -23,9 +22,9 @@ export default async function handler(req: NextRequest) {
2322
return errorResponse("Invalid method", 400);
2423
}
2524

26-
const body = (await req.json()) as FrameRequest;
25+
const body = await req.json();
2726

28-
const { isValid, message } = await CoinbaseKit.validateMessage(body);
27+
const { isValid, message } = await validateFrameMessage(body);
2928

3029
if (!isValid || !message) {
3130
return errorResponse("Invalid message", 400);

apps/dashboard/src/pages/api/superchain/frame.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import type { FrameRequest } from "@coinbase/onchainkit";
21
import * as Sentry from "@sentry/nextjs";
3-
import { CoinbaseKit } from "classes/CoinbaseKit";
42
import { SuperChainFormFrame } from "classes/SuperchainFormFrame";
3+
import { validateFrameMessage } from "lib/farcaster-frames";
54
import type { NextRequest } from "next/server";
65
import {
76
errorResponse,
@@ -27,9 +26,9 @@ export default async function handler(req: NextRequest) {
2726
}
2827

2928
try {
30-
const body = (await req.json()) as FrameRequest;
29+
const body = await req.json();
3130

32-
const { isValid, message } = await CoinbaseKit.validateMessage(body);
31+
const { isValid, message } = await validateFrameMessage(body);
3332

3433
if (!isValid || !message) {
3534
return errorResponse("Invalid message", 400);

apps/dashboard/src/utils/farcaster.ts

Lines changed: 0 additions & 8 deletions
This file was deleted.

apps/dashboard/src/utils/tx-frame.ts

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import type { FrameValidationData } from "@coinbase/onchainkit";
21
import { type ThirdwebContract, encode } from "thirdweb";
32
import { claimTo } from "thirdweb/extensions/erc721";
43

@@ -15,10 +14,3 @@ export async function getErc721PreparedEncodedData(
1514
// Return encoded transaction data
1615
return encodedTransactionData;
1716
}
18-
19-
export const getFarcasterAccountAddress = (
20-
interactor: FrameValidationData["interactor"],
21-
) => {
22-
// Get the first verified account or custody account if first verified account doesn't exist
23-
return interactor.verified_accounts[0] ?? interactor.custody_address;
24-
};

0 commit comments

Comments
 (0)