-
Notifications
You must be signed in to change notification settings - Fork 100
/
Copy pathfarcaster.ts
90 lines (77 loc) · 2.02 KB
/
farcaster.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import type { ClientProtocolId, FrameActionPayload } from "../types";
import {
type FrameMessageReturnType,
getFrameMessage,
} from "../getFrameMessage";
import {
InvalidFrameActionPayloadError,
RequestBodyNotJSONError,
} from "../core/errors";
import type { FramesMiddleware, JsonValue } from "../core/types";
function isValidFrameActionPayload(
value: unknown
): value is FrameActionPayload {
return (
typeof value === "object" &&
!!value &&
"trustedData" in value &&
"untrustedData" in value
);
}
async function decodeFrameActionPayloadFromRequest(
request: Request
): Promise<FrameActionPayload | undefined> {
try {
// use clone just in case someone wants to read body somewhere along the way
const body = await request
.clone()
.json()
.catch(() => {
throw new RequestBodyNotJSONError();
});
if (!isValidFrameActionPayload(body)) {
throw new InvalidFrameActionPayloadError();
}
return body;
} catch (e) {
if (
e instanceof RequestBodyNotJSONError ||
e instanceof InvalidFrameActionPayloadError
) {
return undefined;
}
console.error(e);
return undefined;
}
}
type FrameMessage = Omit<
FrameMessageReturnType<{ fetchHubContext: false }>,
"message"
> & { state?: JsonValue };
type FramesMessageContext = {
message?: FrameMessage;
clientProtocol?: ClientProtocolId;
};
export function farcaster(): FramesMiddleware<any, FramesMessageContext> {
return async (context, next) => {
// frame message is available only if the request is a POST request
if (context.request.method !== "POST") {
return next();
}
// body must be a JSON object
const payload = await decodeFrameActionPayloadFromRequest(context.request);
if (!payload) {
return next();
}
const message = await getFrameMessage(payload, {
fetchHubContext: false,
});
return next({
message,
clientProtocol: {
id: "farcaster",
version: "vNext",
},
});
};
}