Usernames on Farcaster, also known as Fnames, are like Twitter handles. They let others find and mention you on the network.
Fnames are offchain, ENS-compliant names managed by the Farcaster team. Getting an fname is a two-step process. First, you reserve the name through the Fname Registry API. Then, you link it to your FID by submitting a message to a hub.
In this post we’ll focus on the first step, reserving a username. Before you begin, make sure you’ve already set up your account and added a signer:
You can view the complete script on GitHub to copy, customize, or run it end-to-end.
First, decide on a username. Fnames have to meet these requirements:
These rules are enforced by the Fname Registry and match the pattern /^[a-z0-9][a-z0-9-]{0,15}$/
.
import { mnemonicToAccount } from 'viem/accounts';
const FNAME_API_ENDPOINT = 'https://fnames.farcaster.xyz';
const account = mnemonicToAccount(process.env.WALLET_MNEMONIC!);
const fid = Number(process.env.WALLET_FID);
// the username you'd like to reserve
const name = 'dololand';
console.log(`Attempting to reserve "${name}" for fid ${fid}...`);
Make sure wallet’s address if the owner of the FID since you’ll need to sign a verification message in a later step. You can confirm this with the idOf
function of IdRegistry contract if needed.
We can use the Fname Registry API to check if the name is already reserved. It returns ownership info for any name that’s been claimed. If the name isn’t found or isn’t assigned to anyone, it’s available to reserve.
const transferResponse = await fetch(`${FNAME_API_ENDPOINT}/transfers/current?name=${name}`);
const transferData = (await transferResponse.json()) as any;
const isAvailable = transferResponse.status === 404 || transferData.transfer.to === 0;
if (!isAvailable) {
console.log('Username is not available.');
process.exit(0);
}
The script exits early if the name is already taken. You can try again with an alternative. Otherwise, you’re good to move on to the next step.
To reserve a name, the FID owner must sign a message for the claim. The message uses EIP-712 typed data, allowing the API to validate the signature and verify ownership.
const timestamp = Math.floor(Date.now() / 1000); // current time in seconds
const proofMessage = {
name,
owner: account.address,
timestamp: BigInt(timestamp),
};
const proofTypedData = {
domain: {
name: 'Farcaster name verification',
version: '1',
chainId: 1,
verifyingContract: '0xe3be01d99baa8db9905b33a3ca391238234b79d1',
},
types: {
UserNameProof: [
{ name: 'name', type: 'string' },
{ name: 'timestamp', type: 'uint256' },
{ name: 'owner', type: 'address' },
],
},
primaryType: 'UserNameProof',
message: proofMessage,
} as const;
const signature = await account.signTypedData(proofTypedData);
console.log('Proof Signature:', signature);
Now you can send the signature to the Fname Registry API to reserve the name for your FID.
const claimResponse = await fetch(`${FNAME_API_ENDPOINT}/transfers`, {
method: 'post',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name,
from: 0,
to: fid,
fid,
owner: account.address,
signature,
timestamp,
}),
});
const claimData = await claimResponse.json();
console.log('Response:', claimData);
If successful, the name is now reserved.
You’ve successfully reserved an fname for your FID in the Fname Registry and no one else can claim it.
However, it won’t appear in your Farcaster profile just yet. To complete the process, you need to send a message to a hub to set the username.