Skip to main content

Important Note

The Neynar Client Instantiation and API calls (fetchNonce and fetchSigners) should ideally be performed on the backend to protect your API key and maintain security.

Prerequisites

1

Ethereum-Enabled Browser

Browser Ensure you are using a browser with a wallet like MetaMask installed.
2

API Key

Obtain an API key from dev portal
3

Dependencies Installed

Install the required packages:
yarn add siwe viem @neynar/nodejs-sdk

Code Breakdown and Steps

1

Import Required Libraries

The code starts by importing the necessary libraries:
import { SiweMessage } from "siwe";
import { createWalletClient, custom, publicActions } from "viem";
import { optimism } from "viem/chains";
import { NeynarAPIClient, Configuration } from "@neynar/nodejs-sdk";
2

Configure Neynar API Client

Set up the Neynar API client with your API key and base path. Note that this should ideally be done on the backend for security reasons:
const config = new Configuration({
 apiKey: "YOUR_API_KEY_HERE",
});

const client = new NeynarAPIClient(config);
3

Create the Wallet Client

The createWalletClient function initializes a wallet client using the viem library. It uses window.ethereum to connect to the browser’s wallet:
const wallet = createWalletClient({
 chain: optimism,
 transport: custom(window.ethereum),
}).extend(publicActions);
4

Create the SIWE Message

The createSiweMessage function generates a SIWE message with details such as domain, address, and nonce:
async function createSiweMessage(address, statement) {
  const { nonce } = await client.fetchNonce();

  const message = new SiweMessage({
 scheme: "http",
 domain: "localhost:8080",
 address,
 statement,
 uri: "http://localhost:8080",
 version: "1",
 chainId: "1",
 nonce: nonce,
 });

  return message.prepareMessage();
}
5

Sign and Verify the Message

The fetchSigners function retrieves the user’s Ethereum address, generates a SIWE message, signs it, and verifies the signature using the Neynar API.Note:
  1. Neynar API should ideally be accessed from the backend
  2. The address should be the custody_address of the farcaster account (Check custody_address in User API)
async function fetchSigners() {
  const address = (await wallet.getAddresses())[0];

  let message = await createSiweMessage(
 address,
    "Sign in with Ethereum to the app."
 );

  const signature = await wallet.signMessage({ account: address, message });

  const { signers } = await client.fetchSigners({ message, signature });

  return signers;
}
6

Execute the Function

Call the fetchSigners function and handle the response or errors:
fetchSigners()
 .then((signers) => {
 console.log("\n\nsigners:", signers, "\n\n");
 })
 .catch((error) => {
 console.error("error:", error);
 });

Expected Output

[
  {
    "object": "signer",
    "signer_uuid": "19d0c5fd-9b33-4a48-a0e2-bc7b0555baec",
    "public_key": "0xe4abc135d40f8a6ee216d1a6f2f4e82476dff75f71ea53c5bdebca43f5c415b7",
    "status": "approved",
    "fid": 0
  },
  {
    "object": "signer",
    "signer_uuid": "08c71152-c552-42e7-b094-f510ff44e9cb",
    "public_key": "0xe4cd577123def73295dd9991c589b59b48cdc976b5e83a9ad8d2a13fcfcc0e72",
    "status": "approved",
    "fid": 0
  }
]
For additional help, feel free to contact us.
I