Guide to Creating a Farcaster Account with Wallet Integration

This document outlines the steps to successfully create a Farcaster account without having a end user mnemonic.

Follow the example code while reading the guide for better understanding

Prerequisites

  • A browser with a wallet extension (e.g., MetaMask, Coinbase etc.) installed.
  • Access to the Farcaster API and ID Registry smart contract.
  • Familiarity with JavaScript and Ethereum wallet interactions.

Step 1: Connect a Wallet

To connect a wallet in the browser:

  1. Check if the browser supports window.ethereum.
  2. Use eth_requestAccounts to request wallet connection.

Code Example:

if (typeof window === "undefined" || typeof window.ethereum === "undefined") {
  console.error("No wallet is installed.");
  window.open("https://metamask.io/download/", "_blank");
  return;
}

const accounts = await window.ethereum.request({
  method: "eth_requestAccounts",
});
if (accounts.length === 0) {
  console.error("No wallet detected. Please log in to a wallet.");
  return;
}
const userAddress = accounts[0];
console.log("Wallet connected:", userAddress);

Step 2: Switch to the Optimism Network

To interact with the ID Registry contract, ensure the wallet is on the Optimism network.

Code Example:

try {
  await window.ethereum.request({
    method: "wallet_switchEthereumChain",
    params: [{ chainId: "0xA" }], // Optimism chainId in hex
  });
  console.log("Switched to Optimism network.");
} catch (error) {
  console.error("Failed to switch to Optimism network:", error);
  return;
}

Step 3: Fetch FID

Use the GET-/v2/farcaster/user/fid endpoint to retrieve the FID of the account that will be transferred to the wallet's address

Code Example:

const response = await fetch("/api/user");
if (!response.ok) {
  console.error("Failed to fetch FID from the API.");
  return;
}
const data = await response.json();
const fid = data.fid;
if (!fid) {
  console.error("FID not found in the API response.");
  return;
}
console.log("FID fetched:", fid);

Step 4: Generate signTypedData with Viem

To generate a signature for FID registration:

  1. Fetch the nonce from the ID Registry contract.
  2. Create EIP-712 typed data and request a signature from the wallet.

Code Example:

import { createWalletClient, custom, publicActions } from "viem";
import { optimism } from "viem/chains";
import { ID_REGISTRY_ABI, ID_REGISTRY_ADDRESS } from "./constants";

const wallet = createWalletClient({
  chain: optimism,
  transport: custom(window.ethereum),
}).extend(publicActions);

const nonce = await wallet.readContract({
  address: ID_REGISTRY_ADDRESS,
  abi: ID_REGISTRY_ABI,
  functionName: "nonces",
  args: [userAddress],
});

const now = Math.floor(Date.now() / 1000);
const deadline = now + 3600; // 1 hour from now

const domain = {
  name: "Farcaster IdRegistry",
  version: "1",
  chainId: 10,
  verifyingContract: ID_REGISTRY_ADDRESS,
};

const types = {
  Transfer: [
    { name: "fid", type: "uint256" },
    { name: "to", type: "address" },
    { name: "nonce", type: "uint256" },
    { name: "deadline", type: "uint256" },
  ],
};

const message = {
  fid: BigInt(fid),
  to: userAddress,
  nonce: BigInt(nonce),
  deadline: BigInt(deadline),
};

const signature = await wallet.signTypedData({
  account: userAddress,
  domain,
  types,
  primaryType: "Transfer",
  message,
});
console.log("Signature:", signature);

Step 5: Check fname Availability

Before registering a username, check if it is available using the GET-/v2/farcaster/fname/availability endpoint.

Code Example:

const fname = "desired_username";
const response = await fetch(`/api/user/fname/availability?fname=${fname}`);
if (!response.ok) {
  console.error("Failed to check fname availability.");
  return;
}
const data = await response.json();
const isAvailable = data.available;
console.log("Fname availability:", isAvailable);

Step 6: Call the POST-/v2/farcaster/user Endpoint

Submit the required data to create the Farcaster account.

Code Example:

const metadata = {
  bio: "Your bio",
  pfp_url: "https://example.com/profile-pic.jpg",
  url: "https://yourwebsite.com",
  display_name: "Your Display Name",
  location: {
    latitude: 40.7128,
    longitude: -74.006,
  },
};

const response = await fetch("/api/user", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    fid,
    signature,
    requestedUserCustodyAddress: userAddress,
    deadline,
    fname,
    metadata,
  }),
});

if (!response.ok) {
  const errorData = await response.json();
  console.error("Error creating account:", errorData.message);
  return;
}

console.log("Account created successfully!");

Conclusion

By following these steps, you can create an account using the user's wallet. (No mnemonic required)