Farcaster frames proporciona un estándar para convertir casts en aplicaciones interactivas en Farcaster. Estos frames permiten crear encuestas, transmisiones en vivo o galerías interactivas.
¿Sabes lo que es Farcaster?
Si ya eres un usuario experimentado de redes sociales, es posible que hayas escuchado hablar de Farcaster. Farcaster es un protocolo de red social descentralizado que ofrece una serie de beneficios sobre las redes sociales centralizadas, como mayor privacidad, seguridad y libertad.
Si la respuesta a esta pregunta es no, entonces es el momento de que leas este excelente tutorial de Nación Bankless donde podrás aprender qué es este protocolo desde un nivel más básico.
Farcaster frames
Si ya sabes bien lo que es Farcaster y tienes un nivel técnico avanzado es el momento de que aprendas que son los frames que ofrece.
Un frame permite convertir cualquier cast en una aplicación interactiva.
Es un estándar para crear experiencias interactivas y autenticadas en Farcaster. Crea encuestas, transmisiones en vivo o galerías interactivas dentro de Warpcast o cualquier otro cliente de FC.
Los frames amplían el estándar OpenGraph y convierten los static embed en experiencias interactivas. El diagrama a continuación muestra la diferencia entre un OG estándar y un OG frame dentro de Warpcast.

Crear un frame es sencillo: elige una imagen para mostrar y añade botones en los que el usuario pueda hacer clic. Si se hace clic en un botón, recibes una devolución de llamada (callback) y puedes enviar otra imagen con más botones.
Un ejemplo:
Los frames se pueden utilizar para crear una encuesta que se muestra en un feed de Farcaster.

Un ejemplo funcional de un servidor de frames para encuestas se puede encontrar aquí.
Creando el frame inicial
Un frame se crea con simples etiquetas OpenGraph. Para crear la pantalla de la encuesta mencionada anteriormente, crea una URL que devuelva los siguientes metadatos:
<meta property="fc:frame" content="vNext" />
<meta property="fc:frame:image" content="http://...image-question.png" />
<meta property="fc:frame:button:1" content="Green" />
<meta property="fc:frame:button:2" content="Purple" />
<meta property="fc:frame:button:3" content="Red" />
<meta property="fc:frame:button:4" content="Blue" />
Si compartes la URL en un cast, aparecerá como un frame. Para probar que el frame funcione sin transmitir, prueba las herramientas de inserción de Warpcast.
Análisis de clics en botones
Warpcast envía una solicitud POST a la URL con el identificador del botón, el fid del usuario y otra información útil cuando se hace clic en un botón. Los datos están disponibles en una forma no firmada (untrustedData) y una forma firmada (trustedData).
Las encuestas requieren que los datos estén firmados para asegurarnos de que el voto no fue falsificado. Los datos confiables deben desempaquetarse utilizando el punto final ‘verifiedMessage’ en un Hub, y sólo los datos devueltos desde ese punto final deben ser utilizados. Los datos no confiables deben descartarse y nunca confiarse. Algunas aplicaciones que no se preocupan por los datos firmados pueden optar por omitir la verificación y utilizar datos no confiables.
Consulta la sección ‘Frame Signature Packet’ en las especificaciones para ver ejemplos.
Responder a clics en botones con un nuevo frame
Después de que la respuesta se verifica y se registra el voto, necesitamos enviar los resultados de la encuesta al usuario. El servidor genera una imagen que muestra los resultados de la encuesta con una herramienta como satori. Luego responde a la solicitud POST con un código 200 OK que incluye un nuevo frame con los resultados envueltos en un objeto HTML. Así es como lo harías en un marco de trabajo como Node.js.
res.status(200).send(`
<!DOCTYPE html>
<html>
<head>
<meta property="fc:frame" content="vNext" />
<meta property="fc:frame:image" content="http://...image-result.png" />
</head>
</html>
`);
Especificación
El ciclo de vida de un frame se ve así:

Construcción y renderizado de etiquetas de frame
Una página de frame debe tener todas las propiedades requeridas en sus encabezados y puede tener propiedades opcionales. Si faltan propiedades requeridas o alguna propiedad está mal formada, las aplicaciones deben recurrir a mostrar la OpenGraph embed.
Propiedades obligatorias:
Key | Type | Descripción |
---|---|---|
fc:frame | string | Una cadena válida de versión de frame. La cadena debe ser una fecha de lanzamiento (por ejemplo, 2020-01-01) o vNext. Las aplicaciones deben ignorar las versiones que no comprendan. Actualmente, la única versión válida es vNext. |
fc:frame:image | string | Una imagen que debe ser inferior a 10MB y debe tener una relación de aspecto de 1.91:1 |
og:image | string | Una imagen que debe ser inferior a 10MB y debe tener una relación de aspecto de 1.91:1. Alternativa para clientes que no admiten marcos. |
Propiedades opcionales:
Key | Type | Descripción |
---|---|---|
fc:frame:button:$idx | string | Una cadena de 256 bytes que es la etiqueta del botón en la posición $idx .Una página puede contener de 0 a 4 botones. Si hay más de 1 botón presente, los valores de idx deben estar en secuencia comenzando desde 1 (por ejemplo, 1, 2, 3). Si hay una secuencia rota presente (por ejemplo, 1, 2, 4), las aplicaciones no deben renderizar el frame y en su lugar renderizar un OpenGraph embed. Las aplicaciones deben mostrar los botones debajo de la imagen y en orden de índice ascendente. Las aplicaciones deben renderizar todos los botones con el mismo ancho y truncar las etiquetas si no caben. Las aplicaciones pueden usar varias filas para renderizar botones si el espacio es una restricción. |
fc:frame:post_url | string | Una cadena de 256 bytes que contiene una URL válida para enviar el paquete de firma. Si esta propiedad no está presente, las aplicaciones deben hacer una solicitud POST a la URL del frame. |
fc:frame:button:$idx:action | string | Debe ser post o post_redirect . Se establece en post de forma predeterminada si no se especifica ningún valor.Si se establece en post, la aplicación debe realizar la solicitud POST y el servidor del frame debe responder con un 200 OK, que puede contener otro frame. Si se establece en post_redirect , la aplicación debe realizar la solicitud POST y el servidor del frame debe responder con un 302 OK con una propiedad de ubicación establecida en el encabezado.Las aplicaciones deben indicar visualmente que el botón abrirá una nueva URL y deben mostrar advertencias apropiadas al usuario sobre contenido no confiable. |
Propiedades futuras (wip):
Estas propiedades aún no son estables, pero pueden incluirse en una versión futura.
Key | Type | Descripción |
---|---|---|
fc:frame:refresh_period | number | Un periodo en segundos en el que la aplicación debería esperar que la imagen se actualice. Debe ser al menos 30. Las aplicaciones deben establecer un valor predeterminado de 86,400 (1 día) si no se establece o si es inválido. Las aplicaciones pueden optar por no respetar esta recomendación si la imagen no se está actualizando o si la imagen... Una aplicación debe establecer el encabezado de control de caché "max age" con el mismo valor que el período de actualización para garantizar que las CDNs (que a menudo se utilizan) también respeten este estándar. Por ejemplo: Cache-Control: max-age=604800 (igual que la actualización). |
Manejo de un clic en el botón de un frame
Cuando el usuario hace clic en un botón:
- Warpcast crea un mensaje protobuf firmado de Frame Signature.
- Warpcast convierte el protobuf en un mensaje JSON de Frame Signature Packet.
- Warpcast envía el paquete a la
post_url
(si está presente) o a la URL del embed. - El servidor del frame responde con un código 200 OK que puede contener otro frame válido.
- Warpcast muestra un estado de éxito y renderiza el nuevo frame (si está presente).
Firmas de frame
Una firma de frame demuestra que un usuario hizo clic en un botón del frame. Es creada por la aplicación Farcaster y enviada al servidor del frame.
Cuando se hace clic en un botón del frame, la aplicación Farcaster debe generar un FrameAction protobuf. Un FrameAction es un nuevo tipo de mensaje de Farcaster. Al igual que todos los mensajes de FC, debe estar firmado con una clave de cuenta Ed25519 activa (también conocida como firmante) que pertenezca al usuario.
Frame action
message FrameActionBody {
bytes frame_url = 1; // The URL of the frame app
bytes button_index = 2; // The index of the button that was clicked
CastId cast_id = 3; // The cast which contained the frame URĽ
bytes input_text = 4; // The text from the user input (if any)
}
// MessageType and MessageData are extended to support the FrameAction
enum MessageType {
.....
MESSAGE_TYPE_FRAME_ACTION = 13;
}
message MessageData {
oneof body {
...
FrameActionBody frame_action_body = 16
}
}
Un FrameActionBody en un mensaje m es válido solo si pasa estas validaciones:
m.signature_scheme
debe serSIGNATURE_SCHEME_ED25519
.m.data.type
debe serMESSAGE_TYPE_FRAME_ACTION
.m.data.body.type
debe ser unUserDataType
válido.m.data.body.url
debe ser <= 256 bytes.- El índice
m.data.body.button_index
debe ser ≥1 y ≤4.
Paquete de firma de frame
Un paquete de firma es un objeto JSON enviado por Warpcast al servidor del frame cuando se hace clic en un botón. Contiene dos objetos:
1. Mensaje Firmado — un mensaje protobuf firmado que contiene los detalles de la acción que tomó el usuario. Puede ser verificado y desempaquetado por un Farcaster Hub utilizando el punto final validateMessage
. Las aplicaciones deben utilizar esto y deben ignorar datos no autenticados si la autenticación es primordial.
2. Mensaje No Firmado — un objeto JSON no firmado que contiene los detalles de la acción que tomó el usuario. Debería utilizarse sólo cuando el frame no necesita confiar en el usuario.
Las aplicaciones que se preocupan por la autenticación (por ejemplo, una encuesta) deben deserializar el mensaje firmado utilizando un Hub y leer su contenido. No deben usar el mensaje no firmado que puede ser falsificado. También deben validar que la URL dentro del mensaje firmado coincida con la URL del servidor (para detectar casos como fakepolls.fake creando un frame que envía a fcpolls.com
{
"untrustedData": {
"fid": 2,
"url": "https://fcpolls.com/polls/1",
"messageHash": "0xd2b1ddc6c88e865a33cb1a565e0058d757042974",
"timestamp": 1706243218,
"network": 1,
"buttonIndex": 2,
"inputText": "hello world", // "" if requested and no input, undefined if input not requested
"castId": {
"fid": 226,
"hash": "0xa48dd46161d8e57725f5e26e34ec19c13ff7f3b9"
}
},
"trustedData": {
"messageBytes": "d2b1ddc6c88e865a33cb1a565e0058d757042974..."
}
}
El mensaje firmado puede ser validado llamando a la API validateMessage
en los Hubs, como se muestra en el guión a continuación. El hub (suponiendo que esté completamente sincronizado) validará lo siguiente:
- El fid es un farcaster fid válido y registrado.
- El firmante está actualmente activo y asociado con el fid.
- El hash del mensaje es correcto (los contenidos coinciden con el hash).
- La firma para el mensaje es válida y proviene del firmante.
- El FrameActionBody pasa las validaciones anteriores.
Respuesta del servidor de frame
- Un servidor de frame debe responder con un código 200 OK al recibir un paquete de firma de frame.
- Un servidor de frame puede devolver HTML en el cuerpo que contiene otro frame.
- Un servidor de frame debe agregar parámetros de marca de tiempo a las URL de las imágenes para evitar el almacenamiento en caché en las respuestas.
Problemas conocidos / Preguntas abiertas
- ¿Qué sucede cuando un servidor devuelve un error?
- ¿Se pueden enviar mensajes de error a los usuarios?
- ¿Se pueden enviar transacciones a los usuarios?
Justificación
¿Por qué el frame utiliza imágenes estáticas en lugar de contenido dinámico?
Consideramos el uso de iFrames, HTML/CSS, JSON-LD y otros para la superficie interactiva de los frames. Se rechazaron los iFrames debido a problemas de rendimiento en dispositivos móviles y a un modelo de seguridad complejo. HTML/CSS era difícil de usar sin JavaScript, lo que generaba preocupaciones de seguridad. JSON-LD requeriría que cada cliente tradujera JSON a una interfaz de usuario, lo que sería una cantidad considerable de trabajo.
El uso de imágenes OG es sencillo para las aplicaciones de frames con herramientas públicas de imágenes OG. También es fácil para los clientes renderizar de manera agradable, incluso si no conocen el estándar del frame. Aunque no se puede actualizar con tanta frecuencia, garantiza una experiencia de usuario consistente.
¿Por qué las firmas son de claves de cuenta Ed25519 en lugar de direcciones ETH ECDSA?
Se garantiza que todas las aplicaciones de Farcaster tengan un par de claves Ed25519, lo que significa que pueden interactuar con los frames. Sólo las aplicaciones de billetera tendrán acceso a la clave ECDSA para producir firmas. Además, la propiedad puede vincularse a una dirección ETH desde una clave de cuenta a través de las verificaciones.
¿Por qué las firmas son sobre protobufs en lugar de objetos JSON?
No hay un estándar para firmar JSON con claves de cuenta Ed25519. Farcaster ya ha creado un estándar y herramientas para firmar protobufs con Ed25519, lo que resultó fácil de reutilizar. Los protobufs también pueden serializarse a JSON para el transporte a través de la red.
Apéndice: ideas futuras
Estado
El cliente también podría almacenar el castId para cualquier emisión donde el usuario tomó una acción en el frame y siempre agregará ?fid=<userfid>
a la URL. Esto puede ser utilizado por el servidor para mostrar una respuesta personalizada al usuario basada en interacciones anteriores. Esto no se transfiere entre dispositivos, por lo que el servidor debe poder manejar envíos de acciones duplicadas o conflictivas.
Descentralización
- Un contrato inteligente para registrar frames/aplicaciones. Requiere un fid de propietario, una URL a un archivo de metadatos JSON y una firma de la dirección de custodia. Puede requerir un pago adicional.
- Un nuevo campo en el cast para el frame en lugar de un embed. El Hub sólo reconoce frames registrados.
- El Hub almacena x número de las acciones de frame más recientes por usuario (cada frame tiene su propio límite, por lo que un solo frame no puede acaparar el almacenamiento del usuario). Estas están disponibles como mensajes normales para que cualquiera los consulte y se suscriba.
- El frame puede ser revocado a nivel de contrato, lo que revocará todos los mensajes con este frame en caso de abuso.
Apéndice: implementación Warpcast
Notas de Goksu sobre cómo funcionan actualmente los flujos de análisis de Open Graph
- Cuando el usuario escribe una URL en el compositor de un cast, el cliente activa una solicitud de análisis a los servidores de Warpcast.
- Los servidores de Warpcast realizan una solicitud de análisis para obtener los encabezados.
- Los valores de la respuesta se almacenan por URL en Redis.
- Cuando se crea un cast, el servidor activa un trabajo asíncrono de procesar embeds.
- Trabajo asíncrono de procesar embeds:
- Realiza una solicitud para analizar cada URL de embed.
- Si la URL ya está analizada, utiliza el resultado en caché existente de Redis.
- Almacena el conjunto general de resultados de embeds en la columna processed_embeds por cada cast.
- Este proceso no tiene forma de saber qué FID verá cierto embed.
- El proceso puede tener en cuenta al creador FID del cast (y la persona que embebe la URL).
- En el feed principal, vistas de hilos, en cualquier lugar donde se devuelva un cast
- Cada vez que se ejecute una consulta de cast desde nuestra base de datos, incluiremos la columna
processed_embeds
. - Esta columna ya contiene valores de respuesta JSON formateados y, sin ningún procesamiento posterior, se enviará a los clientes.
- Cada vez que se ejecute una consulta de cast desde nuestra base de datos, incluiremos la columna
- Aspectos a tener en cuenta
- Las respuestas de recuperación de URL de embed se almacenan en caché en Redis.
- Para cada cast y sus embeds, los valores de respuesta correspondientes se procesan y dan forma según nuestros tipos de API de Warpcast y se almacenan en la columna
processed_embeds
con cada cast. - Estos objetos se envían a los clientes tal cual.
Si deseas acceder a la documentación técnica de este protocolo puedes hacerlo en este enlace.