Skip to content

Commit 1f3e724

Browse files
feat: frames v2 support (#531)
* chore: frames v2 test app template * fix: cast action message response definition * feat: basic frames v2 parsing * fix: do not cause infinite render cycle when using initialPendingExtra * feat: basic frames v2 support * fix: properly type current frame stack item * refactor: types * feat: useCastAction hook and fixing issues with signer copy * refactor: use new cast action hook and unstable frame hooks in debugger * feat: export signer instance types * chore: add farcaster v2 to protocol selector * fix: make frame v2 parsing compatible with spec * fix: parsing frame button * feat: allow multi spec signer * feat: allow debugger to lock specification * fix: launch button type * chore: define handler for frame launching * feat: add new hook to handle frames v2 app * feat: add app frame dialog * chore: basic frames 2 example * fix: test * test: add farcaster v2 tests * chore: update sdk * fix: unregister exposed comlink listeners * chore: unregister all exposed listeners * feat: add helpers to detect fully valid frames * chore: split parse result types * feat: add json farcaster signature utils * fix: make json signatures browser compatible * feat: add domain account association generator to debugger * chore: add comments * test: signature signing * chore: eslint fix * feat: parse and validate farcaster v2 frames and manifest * fix: make route handlers compatible with async parsing * fix: use 3:2 aspect ratio for frame * feat: support react native * chore: remove our starter * fix: add missing parse result * feat: show fc v1/v2 alert * feat: manifest debugger tab * chore: update peer dep and properly handle events * chore: enable debug mode * fix: throw an error because the error message is not the same as sdk expects * feat: allow to hook into tx, messages and typed data signing * feat: add an option to enable manifest parsing * fix: wait for wallet client * feat: allow to use different connectors * chore: use new provider in debugger * feat: fetch frame in useFrameApp hook * fix: peer dep * chore: return props as object * fix: use iframeProps * fix: eslint issue * chore: export return and option types * fix: check if emitter is really set * chore: update peer deps * fix: frame app dialog layout * chore: remove unnecessary handler * chore: allow to debug eth provider requests * feat: allow to launch app in different contexts * fix: respect abort signal * feat: allow to resolve client * feat: simple notifications support * chore: do not allow to run frame app debugger from cast action debugger * feat: allow to manage frame and notification settings * feat: notifications event log and webhooks * chore: use bigger ttl * chore: add cli options for kv store * chore: integrate farcaster implementation of frames v2 * feat: emit events * chore: rename variables * fix: compilation error * fix: import as type * chore: emit events * fix: do not reload frame app on notifications state changes * chore: do not store signer key * feat: use sqlite if redis is not available * feat: allow non strict parsing * chore: changeset * chore: remove package that doesn't exist * chore: bump facaster/core and protobuf * chore: allow non https urls in debugger notifications endpoints * chore: make sqlite optional dep * fix: event log scrolling * chore: add alert on unsupported signer state * chore: allow impersonated signers * fix: correcly show notifications panel
1 parent ef118a4 commit 1f3e724

File tree

104 files changed

+11275
-2440
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+11275
-2440
lines changed

.changeset/ninety-ducks-melt.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
"frames.js": minor
3+
"@frames.js/debugger": minor
4+
"@frames.js/render": minor
5+
---
6+
7+
feat: farcaster v2 support

packages/debugger/.env.sample

+5-1
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,8 @@ FARCASTER_DEVELOPER_MNEMONIC=
88
# Example: FARCASTER_DEVELOPER_FID=1214
99
FARCASTER_DEVELOPER_FID=
1010

11-
NEXT_PUBLIC_WALLETCONNECT_ID=
11+
NEXT_PUBLIC_WALLETCONNECT_ID=
12+
13+
# Required to debug Farcaster Frames v2 notifications
14+
KV_REST_API_TOKEN=""
15+
KV_REST_API_URL=""

packages/debugger/.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,5 @@ yarn-error.log*
3636
# typescript
3737
*.tsbuildinfo
3838
next-env.d.ts
39-
mocks.json
39+
mocks.json
40+
/notifications.db
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
import { useMemo } from "react";
2+
import type { CastActionDefinitionResponse } from "../frames/route";
3+
import type { ParsingReport } from "frames.js";
4+
import { Table, TableBody, TableCell, TableRow } from "@/components/table";
5+
import { AlertTriangleIcon, CheckCircle2Icon, XCircleIcon } from "lucide-react";
6+
import { cn } from "@/lib/utils";
7+
import { ShortenedText } from "./shortened-text";
8+
9+
function isPropertyExperimental([key, value]: [string, string]) {
10+
return false;
11+
}
12+
13+
type ActionDebuggerPropertiesTableProps = {
14+
actionMetadataItem: CastActionDefinitionResponse;
15+
};
16+
17+
export function ActionDebuggerPropertiesTable({
18+
actionMetadataItem,
19+
}: ActionDebuggerPropertiesTableProps) {
20+
const properties = useMemo(() => {
21+
/** tuple of key and value */
22+
const validProperties: [string, string][] = [];
23+
/** tuple of key and error message */
24+
const invalidProperties: [string, ParsingReport[]][] = [];
25+
const visitedInvalidProperties: string[] = [];
26+
const result = actionMetadataItem;
27+
28+
// we need to check validation errors first because getFrame incorrectly return a value for a key even if it's invalid
29+
for (const [key, reports] of Object.entries(result.reports)) {
30+
invalidProperties.push([key, reports]);
31+
visitedInvalidProperties.push(key);
32+
}
33+
34+
for (const [key, value] of Object.entries(result.action)) {
35+
if (visitedInvalidProperties.includes(key) || value == null) {
36+
continue;
37+
}
38+
39+
if (typeof value === "object") {
40+
validProperties.push([key, JSON.stringify(value)]);
41+
} else {
42+
validProperties.push([key, value]);
43+
}
44+
}
45+
46+
return {
47+
validProperties,
48+
invalidProperties,
49+
isValid: invalidProperties.length === 0,
50+
hasExperimentalProperties: false,
51+
};
52+
}, [actionMetadataItem]);
53+
54+
return (
55+
<Table>
56+
<TableBody>
57+
{properties.validProperties.map(([propertyKey, value]) => {
58+
return (
59+
<TableRow key={`${propertyKey}-valid`}>
60+
<TableCell>
61+
{isPropertyExperimental([propertyKey, value]) ? (
62+
<span className="whitespace-nowrap flex">
63+
<div className="inline">
64+
<CheckCircle2Icon size={20} color="orange" />
65+
</div>
66+
<div className="inline text-slate-500">*</div>
67+
</span>
68+
) : (
69+
<CheckCircle2Icon size={20} color="green" />
70+
)}
71+
</TableCell>
72+
<TableCell>{propertyKey}</TableCell>
73+
<TableCell className="text-slate-500">
74+
<ShortenedText text={value} maxLength={30} />
75+
</TableCell>
76+
</TableRow>
77+
);
78+
})}
79+
{properties.invalidProperties.flatMap(
80+
([propertyKey, errorMessages]) => {
81+
return errorMessages.map((errorMessage, i) => {
82+
return (
83+
<TableRow key={`${propertyKey}-${i}-invalid`}>
84+
<TableCell>
85+
{errorMessage.level === "error" ? (
86+
<XCircleIcon size={20} color="red" />
87+
) : (
88+
<AlertTriangleIcon size={20} color="orange" />
89+
)}
90+
</TableCell>
91+
<TableCell>{propertyKey}</TableCell>
92+
<TableCell className="text-slate-500">
93+
<p
94+
className={cn(
95+
"font-bold",
96+
errorMessage.level === "error"
97+
? "text-red-500"
98+
: "text-orange-500"
99+
)}
100+
>
101+
{errorMessage.message}
102+
</p>
103+
</TableCell>
104+
</TableRow>
105+
);
106+
});
107+
}
108+
)}
109+
{properties.hasExperimentalProperties && (
110+
<TableRow>
111+
<TableCell colSpan={3} className="text-slate-500">
112+
*This property is experimental and may not have been adopted in
113+
clients yet
114+
</TableCell>
115+
</TableRow>
116+
)}
117+
</TableBody>
118+
</Table>
119+
);
120+
}

0 commit comments

Comments
 (0)