Fetch Signers - Frontend (Wallet Integration)

This guide demonstrates how to get a list of signers for an account if the developer can't access the user's mnemonic. (If the developer has access to the mnemonic, check: Backend)

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
    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: Neynar API should ideally be accessed from the backend:

    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.