Skip to content

Instantly share code, notes, and snippets.

@alongcamewayne
Created April 10, 2025 17:27
Show Gist options
  • Select an option

  • Save alongcamewayne/a0773b44f3588e9ff5c6d702281cb7df to your computer and use it in GitHub Desktop.

Select an option

Save alongcamewayne/a0773b44f3588e9ff5c6d702281cb7df to your computer and use it in GitHub Desktop.
Script to create and add a signer to a Farcaster account. https://dololand.com/add-farcaster-signer
/**
* Add a signer to your Farcaster account.
*
* Requirements:
* - Farcaster account (FID) already registered
* - Wallet must control the FID
* - Wallet must have ETH on Optimism for gas
*
* .env file:
* WALLET_MNEMONIC="your twelve word seed phrase"
* WALLET_FID=1234
*/
import * as ed from '@noble/ed25519';
import {
bytesToHex,
createPublicClient,
createWalletClient,
encodeAbiParameters,
http,
} from 'viem';
import { mnemonicToAccount } from 'viem/accounts';
import { optimism } from 'viem/chains';
import {
KEY_GATEWAY_ADDRESS,
keyGatewayABI,
SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_TYPES,
signedKeyRequestValidatorABI,
} from '@farcaster/core';
// Load the wallet and FID from environment variables
const account = mnemonicToAccount(process.env.WALLET_MNEMONIC!);
const fid = Number(process.env.WALLET_FID);
console.log('Account Address:', account.address);
console.log('Account FID:', fid);
// Generate a new Ed25519 keypair to use as a signer
const privateKey = ed.utils.randomPrivateKey();
const signerKeypair = {
privateKey: bytesToHex(privateKey),
publicKey: bytesToHex(await ed.getPublicKeyAsync(privateKey)),
};
console.log('Signer Public Key:', signerKeypair.publicKey);
console.log('Signer Private Key:', signerKeypair.privateKey);
// Set a deadline (24 hours from now) for the key authorization to be valid
const deadline = BigInt(Math.floor(Date.now() / 1000) + 86400);
// Construct and sign the EIP-712 typed data payload for authorizing the signer
const keyRequestData = {
...SIGNED_KEY_REQUEST_VALIDATOR_EIP_712_TYPES,
primaryType: 'SignedKeyRequest',
message: {
requestFid: BigInt(fid),
key: signerKeypair.publicKey,
deadline,
},
} as const;
const signature = await account.signTypedData(keyRequestData);
console.log('Signed Key Request:', signature);
// Encode the signed key request into ABI-encoded metadata for the contract
const metadata = encodeAbiParameters(signedKeyRequestValidatorABI[12].inputs, [
{
requestFid: BigInt(fid),
requestSigner: account.address,
signature,
deadline,
},
]);
// Create a read-only client to simulate the transaction
const publicClient = createPublicClient({
chain: optimism,
transport: http(),
});
// Simulate the `add` call to prepare the transaction for submission
const { request } = await publicClient.simulateContract({
account,
address: KEY_GATEWAY_ADDRESS,
abi: keyGatewayABI,
functionName: 'add',
args: [1, signerKeypair.publicKey, 1, metadata],
});
console.log(request);
// Create a wallet client to send the actual transaction
const walletClient = createWalletClient({
chain: optimism,
transport: http(),
});
// Submit the transaction to register the signer onchain
const txn = await walletClient.writeContract(request);
console.log(`Transaction: https://optimistic.etherscan.io/tx/${txn}`);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment