earth

Register a Farcaster ID (FID) with Viem

April 9, 2025

Every Farcaster account is tied to a Farcaster ID (FID), a unique onchain identifier owned by an Ethereum wallet. Let’s write a script to create a new account by registering an FID.

What you’ll need:

  • An Ethereum wallet
  • Enough Optimism ETH to cover registration and gas (~$2 at time of writing)

You can view the complete script on GitHub to copy, customize, or run it end-to-end.

Setup

First, create a new project and install our dependencies:

bun init -y
bun add viem @farcaster/core

Get a Wallet

Start by setting up the Ethereum wallet that will own the Farcaster ID. You can either create a new one or load an existing wallet.

Create a new wallet

This generates a fresh seed phrase and derives an account from it:

import { english, generateMnemonic, mnemonicToAccount } from 'viem/accounts';

const mnemonic = generateMnemonic(english);
const account = mnemonicToAccount(mnemonic);

console.log('Account Mnemonic:', mnemonic); // lock mix ...
console.log('Account Address:', account.address); // 0x...
⚠️ Important: If you generate a new wallet, store the seed phrase securely. Anyone with access to it can take control of the wallet and your Farcaster ID. Never commit it to version control.

Use an existing wallet

If you already have a wallet, we need to load it using a mnemonic (or private key). Create a .env file with the following values:

WALLET_MNEMONIC="your twelve word seed phrase"
# or
# WALLET_PRIVATE_KEY=0x...

Now we can use it in our script:

import { mnemonicToAccount } from 'viem/accounts';

// or if using a private key, use privateKeyToAccount
const account = mnemonicToAccount(process.env.WALLET_MNEMONIC!);
console.log('Account Address:', account.address); // 0x...

Check for an Existing FID

If you’re using a new wallet, you can skip this step. This checks whether the wallet already has a registered Farcaster ID (FID):

import { createPublicClient, http } from 'viem';
import { optimism } from 'viem/chains';
import { ID_REGISTRY_ADDRESS, idRegistryABI } from '@farcaster/core';

// ...

const publicClient = createPublicClient({
	chain: optimism,
	transport: http(),
});

let fid = await publicClient.readContract({
	address: ID_REGISTRY_ADDRESS,
	abi: idRegistryABI,
	functionName: 'idOf',
	args: [account.address],
});

if (fid) {
	console.log(`Wallet already has an fid: ${fid.toString()}`);
	process.exit(0);
}

The script exits early if the wallet already has an FID. A wallet can only own one.

Check the Registration Price

You’ll need at least this much Optimism ETH to cover the registration fee. Make sure the wallet has enough ETH for both the registration and gas fees.

// update imports
import { createPublicClient, formatEther, http } from 'viem';
import {
	ID_GATEWAY_ADDRESS,
	ID_REGISTRY_ADDRESS,
	idGatewayABI,
	idRegistryABI,
} from '@farcaster/core';

// ...

const price = await publicClient.readContract({
	address: ID_GATEWAY_ADDRESS,
	abi: idGatewayABI,
	functionName: 'price',
});

console.log(`Registration cost: ${formatEther(price)} ETH`);

Submit the Transaction

Before registering, choose a recovery address. This address can be used to recover your Farcaster account if you lose access to the wallet that owns the FID.

For simplicity, we’ll use the recovery proxy address provided by Warpcast:

//  update imports
import { createPublicClient, createWalletClient, formatEther, http, type Hex } from 'viem';

// ...

const walletClient = createWalletClient({
	chain: optimism,
	transport: http(),
});

const WARPCAST_RECOVERY_PROXY: Hex = '0x00000000FcB080a4D6c39a9354dA9EB9bC104cd7';

const { request } = await publicClient.simulateContract({
	account,
	address: ID_GATEWAY_ADDRESS,
	abi: idGatewayABI,
	functionName: 'register',
	args: [WARPCAST_RECOVERY_PROXY, 0n],
	value: price,
});

const txn = await walletClient.writeContract(request);
console.log(`Transaction: https://optimistic.etherscan.io/tx/${txn}`);

Get your FID

Once the transaction is confirmed, you can retrieve your newly assigned FID by querying the ID Registry contract:

// ...

fid = await publicClient.readContract({
	address: ID_REGISTRY_ADDRESS,
	abi: idRegistryABI,
	functionName: 'idOf',
	args: [account.address],
});

console.log(`FID: ${fid.toString()}`);

Next Steps

Now you have a Farcaster account with an FID, but having just an FID isn’t much fun. Before you start casting, you’ll want to:

Add a signer

Signers let apps post on your behalf without exposing your main wallet. Most clients use signers to handle actions like casting, following, or updating your profile. If you haven’t added a signer yet, you’ll need to do that first, here’s a guide to help you get started.

Claim a username and update your profile

Set a human-readable username, add a profile picture, and write a short bio. This makes your account recognizable across Farcaster clients.

Send your first cast

A cast is Farcaster’s version of a post. Once your account is ready, you can start sharing messages on the network just like tweeting, but decentralized.