This guide walks you through generating a Signed Key Request using viem
that need to be passed in while registering auth address
System & Installation Requirements
Prerequisites
- Node.js >= 18.x (LTS recommended)
- npm >= 9.x OR yarn >= 1.22.x
Download and install node (if not installed)
Initialize project (optional)
mkdir signed-key-request
cd signed-key-request
npm init -y
Install viem
OR with yarn:
Code Breakdown and Steps
You can find full code at the end of this guide.
Import the required functions
The code starts by importing the necessary libraries:
import { encodeAbiParameters } from "viem";
import { mnemonicToAccount, generateMnemonic, english } from "viem/accounts";
Generate a random mnemonic and derive the auth address
Generates a mnemonic and converts it to an Ethereum address (auth_address
)
const mnemonic = generateMnemonic(english);
const auth_address_acc = mnemonicToAccount(mnemonic);
const auth_address = auth_address_acc.address;
Define EIP-712 domain
Describes the EIP-712 domain (context of signature).
const SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN = {
name: "Farcaster SignedKeyRequestValidator",
version: "1",
chainId: 10,
verifyingContract: "0x00000000fc700472606ed4fa22623acf62c60553",
};
Define the EIP-712 message structure
Defines the structure of the message to be signed.
const SIGNED_KEY_REQUEST_TYPE = [
{ name: "requestFid", type: "uint256" },
{ name: "key", type: "bytes" },
{ name: "deadline", type: "uint256" },
];
Encode the auth_address
Encodes auth_address
as 32 bytes.
const key = encodeAbiParameters(
[{ name: "auth_address", type: "address" }],
[auth_address]
);
App details
Replace "MNEMONIC_HERE"
with your app mnemonic phrase and fid with your app’s fid.
const fid = 0;
const account = mnemonicToAccount("MNEMONIC_HERE");
Define a deadline
Sets a 24-hour expiration time.
const deadline = Math.floor(Date.now() / 1000) + 86400;
Sign the EIP-712 message
Signs the message per EIP-712 standard.
const signature = await account.signTypedData({
domain: SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN,
types: {
SignedKeyRequest: SIGNED_KEY_REQUEST_TYPE,
},
primaryType: "SignedKeyRequest",
message: {
requestFid: BigInt(fid),
key,
deadline: BigInt(deadline),
},
});
Create a sponsor signature
If you want to sponsor the auth address, you can sign the EIP-712 signature again with a basic Ethereum signature.
This route needs to be sponsored if not provided then neynar will sponsor it for you and you will be charged in compute units.
const sponsorSignature = await account.signMessage({
message: { raw: signature },
});
Print output
Prints useful values for further use.
console.log("auth_address", auth_address);
console.log("app_fid", fid);
console.log("signature", signature);
console.log("deadline", deadline);
console.log("sponsor.signature", sponsorSignature);
console.log("sponsor.fid", fid);
Run the code
Save the code in a file, e.g., generateSignedKeyRequest.js
, and run it using Node.js:
node generateSignedKeyRequest.js
cURL
Use the generated values to make a cURL request to register the auth address.
Replace <api-key>
with your actual API key and <string>
with your redirect URL(if needed).
curl --request POST \
--url https://api.neynar.com/v2/farcaster/auth_address/developer_managed/signed_key/ \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '{
"address": "0x5a927ac639636e534b678e81768ca19e2c6280b7",
"app_fid": 3,
"deadline": 123,
"signature": "0x16161933625ac90b7201625bfea0d816de0449ea1802d97a38c53eef3c9c0c424fefbc5c6fb5eabe3d4f161a36d18cda585cff7e77c677c5d34a9c87e68ede011c",
"redirect_url": "<string>",
"sponsor": {
"fid": 3,
"signature": "<string>",
"sponsored_by_neynar": true
}
}'
Full Final Code
import { encodeAbiParameters } from "viem";
import { mnemonicToAccount, generateMnemonic, english } from "viem/accounts";
(async () => {
const mnemonic = generateMnemonic(english);
const auth_address_acc = mnemonicToAccount(mnemonic);
const auth_address = auth_address_acc.address;
const SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN = {
name: "Farcaster SignedKeyRequestValidator",
version: "1",
chainId: 10,
verifyingContract: "0x00000000fc700472606ed4fa22623acf62c60553",
};
const SIGNED_KEY_REQUEST_TYPE = [
{ name: "requestFid", type: "uint256" },
{ name: "key", type: "bytes" },
{ name: "deadline", type: "uint256" },
];
const key = encodeAbiParameters(
[{ name: "auth_address", type: "address" }],
[auth_address]
);
const fid = 0;
const account = mnemonicToAccount("MNEMONIC_HERE");
const deadline = Math.floor(Date.now() / 1000) + 86400;
const signature = await account.signTypedData({
domain: SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_DOMAIN,
types: {
SignedKeyRequest: SIGNED_KEY_REQUEST_TYPE,
},
primaryType: "SignedKeyRequest",
message: {
requestFid: BigInt(fid),
key,
deadline: BigInt(deadline),
},
});
const sponsorSignature = await account.signMessage({
message: { raw: signature },
});
console.log("auth_address", auth_address);
console.log("app_fid", fid);
console.log("signature", signature);
console.log("deadline", deadline);
console.log("sponsor.signature", sponsorSignature);
console.log("sponsor.fid", fid);
})();
Enjoy building! 🚀
For additional help, feel free to contact us.