-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
LIP 24 - Lens Frame Standard #52
base: main
Are you sure you want to change the base?
LIP 24 - Lens Frame Standard #52
Conversation
|
This makes total sense to me and well thought out with native support now on lens SDK and APIs this looks good to go! it can only benefit and bring innovation onto lens more |
Looks solid at first sight. No support for audio or video? Via audio and video tags, to reduce any security issues. Might add some new options. |
@mvanhalen we've been thinking about video and audio in the Open Frames spec as well. The first version of the OF spec draft had a We didn't ship it in V1 because we were really prioritizing Farcaster compatibility. But it might be time to re-open that conversation and see if it makes sense to add (in addition to the existing required |
this is really exciting and I am a huge fan of bringing frames to Lens using an open standard. I have immediate use for this standard ! |
That would be a great feature to v2 |
I had a couple of questions about the specifics of the implementation
Curious what this will be used for and when an unauthenticated response is desirable. If there's a strong reason, maybe it's something that could be PR'd to the Open Frames spec
In XMTP's implementation of Open Frames we put everything into a serialized proto to keep the We could make the |
Frames has unleashed a massive wave of creativity in the Farcaster ecosystem, and it'll be great to see what this open standard will do in the Lens ecosystem and beyond. We are all building and gesturing towards a future state of decentralized social that looks and feels different than a simple Twitter clone. Having more designers and builders play and experiment with this open standard is a positive step in the right direction. |
The reason this is included is in case a frame does not require an authenticated response (such as informational frames or linking to an external site) then removing the sign/verify steps allows apps to know that they should show or hide certain frames depending on if a user is logged in, and also it can reduce the latency of interactions. I was actually thinking that this could be a good addition to the Open Frames standard as well so I'll open a PR for this tomorrow. On the Thanks for the feedback @neekolas ! |
This is an exciting proposal and continued progress forward toward open standards, creative innovation, and permissionless building. Frames really pushes the boundaries of what's possible in the space and to see them come to life on Lens is something to behold. |
Abstract
This proposals introduces a specification for Lens Frames, and proposes that it is adopted as a standard for Lens developers. Lens frames are an implementation of Open Frames, a standard set of tags and procedures for developers to integrate Lens authentication and functionality into frames. The specification also proposes a new text publication metadata field:
preferredFrame
, to embed Lens publications and open actions as frames.Motivation
Frames are an extension of the OpenGraph protocol that enable interactive elements to be embedded between web applications.
A frame is a session between a frontend and frame server. The frame server exposes visual elements and actions that are able to be interacted through a frontend that embeds the frame. Frames can represent a wide variety of applications including informational guides, games, Web3 transactions, image galleries, e-commerce, live data, and much more.
A frame session is also able to incorporate authentication protocols, allowing the frame server to verify the inputs and identity of a user. The Open Frames standard is a set of standard frame tags that enables a frame to share visual elements and specify support between different authentication protocols.
The motivation for creating this proposal is so that applications and frame developers can agree upon a set of frame tags, features, and procedures to verify frame requests by Lens Profiles. This reduces fragmentation of features between Lens applications and enhances the capabilities of Lens creators to expose new types of frontends for their Lens publications and modules.
Specification & Rationale
The Lens frame specification that is proposed to be adopted is here: https://github.com/defispartan/lens-frames.git
It is planned to be maintained at this location and updated according to semantic versioning. The full specification is also copied below.
Overview
Frames are an extension of the OpenGraph protocol that enable interactive elements to be embedded between web applications.
A frame is a session between a frontend and frame server. The frame server exposes visual elements and actions that are able to be interacted through a frontend that embeds the frame. Frames can represent a wide variety of applications including informational guides, games, Web3 transactions, image galleries, e-commerce, live data, and much more.
A frame session is also able to incorporate authentication protocols, allowing the frame server to verify the inputs and identity of a user. Open Frames is a set of standard frame tags that enables visual elements of frames to be shared between protocols.
The Lens Frames specification is an implementation of Open Frames that defines a standard to create interactive applications that integrate Lens Protocol authentication and functionality.
The highlights of the Lens Frames specification are:
Specification
A frame is a set of tags returned within the of an HTML page.
If a page contains all required frame properties, apps will render the page as a frame. The frame tags extend the OpenGraph protocol.
A frame app begins with an initial frame which is cached by apps and shown to users. A frame must have an image. It may have buttons, which when clicked load other frames or redirect the user to external websites.
Tags
A frame property is a meta tag with a property and a content value.
Required Properties
In compliance with the Open Frames standard, use a meta tag in your frame's HTML to declare the client protocols your frame supports.
of:version
1.0.0
of:accepts:lens
1.0.0
.of:image
1.91:1
or1:1
.og:image
1.91:1
. Fallback for clients that do not support frames.Optional properties
of:button:$idx
$idx
. Buttons are 1-indexed. Maximum 4 buttons per Frame.$idx
values must be rendered in an unbroken sequence.of:button:$idx:action
post
,post_redirect
,mint
,link
, andtx
. Default:post
of:button:$idx:target
post
,post_redirect
, and link action types the target is expected to be a URL starting withhttp://
orhttps://
. For the mint action type the target must be a CAIP-10 URLof:button:$idx:post_url
of:post_url
of:post_url
http://
orhttps://
. Maximum 256 bytes.of:input:text
of:image:aspect_ratio
of:image
field. Allowed values are1.91:1
and1:1
. Default:1.91:1
of:image:alt
of:state
of:authenticated
true
orfalse
. Default:true
Images
There are a few rules for serving images in
of:image
tags:Clients may resize larger images or crop those that do not fit in their aspect ratio. SVG images are not because they can contain scripts and extra work must be done by clients to sanitize them.
When a frame server receives a POST request:
Frame servers can use cache headers to refresh images and offer more dynamic first frame experiences:
Frame servers can use the max-age directive in the HTTP Cache-Control header to ensure images in the initial frame refresh automatically. A lower max-age ensures images update regularly without user interactions. App developers should respect cache headers set by the original frame image, and their image proxy implementations should not interfere with durations.
It is recommended to add timestamps or UUIDs to image urls on subsequent frames to bust caches, and return a frame with a "refresh" button if it is expected that a frame response could take > 5 seconds.
Button actions
post
The
post
action sends a HTTP POST request to the frame or buttonpost_url
. This is the default button type.The frame server receives a signed frame action payload in the POST body, which includes information about which button was clicked, text input, and the cast context. The frame server must respond with a
200 OK
and another frame.post_redirect
The
post_redirect
action sends an HTTP POST request to the frame or buttonpost_url
. You can use this action to redirect to a URL based on frame state or user input.The frame server receives a signed frame action payload in the POST body. The frame server must respond with a
302 Found
andLocation
header that starts withhttp://
orhttps://
.link
The
link
action redirects the user to an external URL. You can use this action to redirect to a URL without sending a POST request to the frame server.Clients do not make a request to the frame server for link actions. Instead, they redirect the user to the
target
URL.mint
The
mint
action allows the user to mint an NFT. Clients that support relaying or initiating onchain transactions may enhance the mint button by relaying a transaction or interacting with the user's wallet. Clients that do not fall back to linking to an external URL.The target property must be a valid CAIP-10 address, plus an optional token ID appended with a
:
.tx
The
tx
action allows a frame to send a transaction request to the user's connected wallet. Unlike other action types, tx actions have multiple steps.First, the client makes a POST request to the
target
URL to fetch data about the transaction. The frame server receives a signed frame action payload in the POST body, which includes theprofileId
and optionalsigner
field that can be verified using the authentication steps. The frame server must respond with a200 OK
and a JSON response describing the transaction which satisfies the following type:Ethereum Params
If the method is
eth_sendTransaction
and the chain is an Ethereum EVM chain, the param must be of typeEthSendTransactionParams
:abi
: JSON ABI which MUST include encoded function type and SHOULD include potential error types. Can be empty.to
: transaction recipientvalue
: value to send with the transaction in wei (optional)data
: transaction calldata (optional)Example:
The client then sends a transaction request to the user's connected wallet, or uses the calldata to generate a signed or dispatched action for Lens protocol actions following instructions here. The client should then send a POST request to the
post_url
with a signed frame action payload including the transaction hash in theactioNResponse
field to which the frame server should respond with a200 OK
and another frame.Frame Requests
When a user clicks a button on a frame, the frame receives a POST request with the payload format below. The payload contains
untrustedData
, containing details of the action taken, andtrustedData
, an EIP-712 signed message from a profile owner or delegated executor used to verify the authenticity ofuntrustedData
.Authentication
When a frame server receives a request, the server is able to verify that the contents of
untrustedData
are authorized by the associated LensprofileId
using the steps described here.A Lens Profile is an NFT with one owner address and any number of delegated executors, addresses with the ability to execute actions on a profile's behalf. Lens frame authentication is based on verifying EIP-712 signed typed data from a profile owner or delegated executor.
Frame Request EIP-712 Typed Data
Any address that has signless interactions enabled has approved the Lens API as a delegated executor, this is recommended as the default form of authentication to enable frame interactions without manual signatures. The end-to-end process of authenticating a frame request is as follows:
1.) Lens application requests a frame signature from Lens API OR the currently connected address if profile does not have signless actions enabled on Lens API. Methods for constructing and signing typed data are detailed in integration section.
2.) Lens application sends POST request to frame server with
trustedData
fields populated based on (1).3.) Frame server verifies signature by constructing typed from frame request and validating that message is signed by profile owner or delegated executor. Methods for constructing and verifying typed data are detailed in building section.
Build Lens Frames
A minimum viable frame consists of a web server serving tags from the Lens specification. When a frame server receives a request to the
post_url
orurl
(depending on which is specificed), it can: perform authentication, perform background actions, update frame state.A frame can authenticate the Lens profile id that originated a request, the address that signed the request (profile owner or delegated executor), and that the content of the request matches what the profile signed. It can do so utilizing the
trustedData
fields as described in authentication.The following sections detail how frame servers can utilize various methods to authenticate a Frame request:
Lens Client SDK
NodeJS script to create and verify typed data from Lens Client SDK based on
untrustedData
andtrustedData
inputs from frame request. Install library with preferred package manager:Lens API
Production endpoint: https://api-v2.lens.dev
NodeJS script to create and verify typed data from Lens API based on
untrustedData
andtrustedData
inputs from frame request. No libraries required, example uses built-infetch
method.Authentication may be abstracted by utilizing a frame library that supports Lens frame authentication. Instructions will be linked here once support is added for popular libraries: frames.js (in progress), onchainkit, and frog.
Integrate Lens Frames
A client Application is where Frames are rendered. A publication containing Frame tags has elements rendered based on the Frame specification and individual tags/values of the Frame instance.
When a user clicks a button on a frame, the app makes a POST request to the frame server. The server must respond with a new frame that is sent back to the user.
The Frame lifecycle begins when a user creates a publications containing a frame URL. The client application should:
Rendering Frames
Apps may render frames any time they are showing a Lens Publication to a viewer. The following rules apply to the rendering of frames:
of:image:aspect_ratio
property.If the button is a
post_redirect
orlink
action:If the button is a
mint
action, the following rules also apply:target
property.If the button is a
tx
action, validation should be performed at the discretion of the app with recommendations described hereHandling Clicks
If the button clicked is a
post
orpost_redirect
, apps must:of:button:$idx:target
if presentof:post_url
if target was not present.If the button clicked is a
mint
, apps should:If the button is a tx action:
Must visually indicate that a tx button will request a wallet transaction.
Must display the button label provided by the frame.
Handling Responses
Applications will receive responses from frame servers after a POST request is submitted. The following rules apply to the handling of these responses:
post
, treat all non-200 responses as errors.post_redirect
, treat all non-30X responses as errors.http://
orhttps://
.Signing Frame Requests
A frame can authenticate the Lens profile id that originated a request, the address that signed the request (profile owner or delegated executor), and that the content of the request matches what the profile signed. It can do so utilizing the
trustedData
fields as described in authentication.The following sections detail how frame servers can utilize various methods to authenticate a Frame request:
Lens Client SDK
The process for signing frame requests depends on whether the profile has Lens API signless interactions enabled. To check if signless is enabled:
Signless Enabled
NodeJs script using Lens Client SDK to query whether profile has Lens API signless interactions enabled.
If signless is enabled, then the Lens API can sign frame requests on behalf of a user. The SDK method documented below can be used to generated a frame request signature.
Sign Frame Request
NodeJs script using Lens Client SDK to generate frame request signature. Note: requires profile to be logged into API session, login details.
If signless is not enabled for a profile then a frame request must be manually signed by the profile owner or a delegated manager. An application can either choose to disable frame interactions if this is the case, or generate and request that a user sign each frame using
signTypedData
wallet method. The following method can be used to generate typed to sign based on the frame request.Create Typed Data
NodeJs script using Lens Client SDK to generate typed data to sign for frame request.
Lens API
Production endpoint: https://api-v2.lens.dev
The process for signing frame requests depends on whether the profile has Lens API signless interactions enabled. To check if signless is enabled:
Signless Enabled
NodeJs script using Lens API to query whether profile has Lens API signless interactions enabled.
If signless is enabled, then the Lens API can sign frame requests on behalf of a user using the endpoint documented below.
Sign Frame Request
NodeJs script using Lens API to generate signature for frame request. Note: requires profile to be logged into API session using ACCESS_TOKEN, login details.
If signless is not enabled for a profile then a frame request must be manually signed by the profile owner or a delegated manager. An application can either choose to disable frame interactions if this is the case, or generate and request that a user sign each frame using
signTypedData
wallet method. The following API endpoint can be used to generate typed to sign based on the frame request.Create Typed Data
NodeJs script using Lens API to generate typed data to sign for frame request.
Transaction / Open Action
Applications should perform validation to ensure that users are not exposed to harmful actions, and display a detailed prompts (and potentially simulation) to inform users of the action being taken.
The recommended form of validation for Lens Applications is only allowing transactions that interact with Lens Protocol contracts, and if the action is a custom module such as an open action: verifying that the transaction originated from within a Lens publication, and the transaction data matches an open action address embedded in the publication.
An open action is a smart contract module embedded in a Lens publication. When a Lens application receives a transaction response, the app can check whether the destination address (and potentially parameters from initialize calldata as well) matches one of the open action modules attached to the publication. This is the recommended form of validating transactions because it is able to verify the intent of the user creating the publication, and also allows applications to maintain a list of recognized open action contract addresses that are able to be embedded.
Application can also validate using an allowlist of URLs for the transaction request, or a combination of open action and URL validation.
Publications as Frames / Lens Protocol Actions
The LIP (Lens Improvement Proposal) to introduce Lens Frames also proposes to add a publication metadata field:
preferredFrame
. The field enables Lens publication to appear in a feed, and automatically have the modules it contains (reference modules and open actions) rendered as transaction frames within a Lens application feed.The
preferredFrame
metadata field enables application developers to build a new open action, or a frontend for an existing action, and have it automatically embedded when a publication with the module appears in a Lens application feed.The Lens API and SDK infrastructure provide methods to sponsor transactions of core protocol actions and modules that are verified. Lens applications can use this infrastructure to allow transaction frames to be executed as gasless or signless interactions. For now, the process of decoding transactions parameters and encoding them into methods for gasless/signless transactions within Lens infrastructure would need to be done manually using ABI returned with transaction. In the future, they may be helper methods to more easily convert a transaction frame response to a sponsored equivalent.
Changelog
Future Developments
preferredFrame
metadataCopyright
Copyright and related rights waived via CC0.