Signatures
Farcaster Frames have the ability to instruct an App to invoke and sign EIP-712 signatures (see the spec).
Overview
At a glance:
- A Frame has a
<Button.Signature>
element with a specified target.signature
route. - When the user presses the button in the App, the App will make a
POST
request to the.signature
route. - The App uses the response to forward the transaction data to the user's wallet for signing.
- Once the user has signed the data, the App will perform a
POST
request to the frame.
Example
Here is a trivial example on how to expose a signature interface in a frame. We will break it down below.
src/index.tsx
import { Button, Frog } from 'frog'
export const app = new Frog({ title: 'Frog Frame' })
app.frame('/', (c) => {
return c.res({
action: '/finish',
image: (
<div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
Sign data
</div>
),
intents: [
<Button.Signature target="/sign">Sign</Button.Signature>,
]
})
})
app.frame('/finish', (c) => {
const { transactionId } = c
return c.res({
image: (
<div style={{ color: 'white', display: 'flex', fontSize: 60 }}>
Signature: {transactionId}
</div>
)
})
})
app.signature('/sign', (c) => {
return c.signTypedData({
chainId: 'eip155:84532',
domain: {
name: 'Ether Mail',
version: '1',
chainId: 1,
verifyingContract: '0xCcCCccccCCCCcCCCCCCcCcCccCcCCCcCcccccccC',
},
types: {
Person: [
{ name: 'name', type: 'string' },
{ name: 'wallet', type: 'address' },
{ name: 'balance', type: 'uint256' },
],
Mail: [
{ name: 'from', type: 'Person' },
{ name: 'to', type: 'Person' },
{ name: 'contents', type: 'string' },
],
},
primaryType: 'Mail',
message: {
from: {
name: 'Cow',
wallet: '0xCD2a3d9F938E13CD947Ec05AbC7FE734Df8DD826',
balance: 0n,
},
to: {
name: 'Bob',
wallet: '0xbBbBBBBbbBBBbbbBbbBbbbbBBbBbbbbBbBbbBBbB',
balance: 1n,
},
contents: 'Hello, Bob!',
},
})
})
Bonus: Learn the API
You can learn more about the signature APIs here: