Build "Suggested follow list" based on OpenRank and Neynar

Surface suggested follow list from your network.

In all these cases, this guide can be used as a reference, whether it is to display a suggested follow list on the user's homepage or to provide a suggested follow list when a user follows another user (similar to Twitter/X).

This guide expects you to have already have signed up for a Neynar account and have the basics set up ready to be able to consume Neynars' APIs. If you haven't, you can go through the getting started guide here.

Step 1: Fetching the user FID

This is specifically tailored to your client's specifications, particularly in how it manages user data storage. However, the USER_FID will be utilized to retrieve the personalized network and to identify and filter out already followed FIDs from that list of individuals in the personalized network. The subsequent steps will provide further detail on how these components interconnect.

// Getting the USER FID
const USER_FID = 2025;

Step 2: Fetching FIDs in the users personalized network

In this step, we create a function called fetchPersonalizedRankings, which takes an FID as a required parameter and returns a list of user arrays sorted based on their ranking, essentially representing the FID's network.

At the conclusion of this step, we now have a variable called personalizedNetworkRankedArray, which is an array containing all the people in my personalized network based on engagement. To learn more about how these rankings work, refer to this resource.

A brief overview of the other parameters:

  • k: Determines the width of the network mapping.

  • limit (maximum 5000): Used to restrict the returned response limit.

  • lite: Defaults to true and is utilized to reduce the response payload to only include an FID and its corresponding score.

// Step 2: Using Personalized Rankings API to find people in your extended network
async function fetchPersonalizedRankings (fid, k = 3, limit = 1000, lite = true) {
    const personalizedRankingsBaseURL = 'https://graph.cast.k3l.io/scores/personalized/engagement/fids'
    const personalizedRankingsParameters = `k=${k}&limit=${limit}&lite=${lite}`
    const personalizedRankingsURL = `${personalizedRankingsBaseURL}?${personalizedRankingsParameters}`
    const personalizedRankingsResponse = await fetch(personalizedRankingsURL, {
        method: 'POST',
        headers: {
            "Content-Type": "application/json"
        },
        body: JSON.stringify([fid])
    });
    const personalizedNetworkRankedArray  = await personalizedRankingsResponse.json().then(element => element.result).then(element => element.slice(1))
    const filteredPersonalizedNetworkRankedArray = personalizedNetworkRankedArray.map(element => element.fid)
    return filteredPersonalizedNetworkRankedArray
}
const personalizedNetworkRankedArray = await fetchPersonalizedRankings(USER_FID)
console.log('Step 2 Personalized Network Ranked Array: ', personalizedNetworkRankedArray);

Step 3: Find all of the following for an FID using Neynars API

From the previous step, we have an array of FIDs in our extended network. In this step, we are constructing another array containing all the users whom the user's FID is following. To achieve this, we've developed a small function called fetchAllFollowing, which accepts an FID as the query parameter and returns an array of users whom the input FID is following.

We're storing information about this in a variable called usersFollowing, and then creating another variable called filteredUsersFollowing, which exclusively retains the followed FIDs in the array, eliminating all unnecessary information. Therefore, we now have another array named filteredUsersFollowing, which contains all the FIDs that the user is following

usersFollowingArray is the final array in which we are storing the result of this function, which is an array of FIDs that are being followed by the user

// Step 3: Using Neynars API to find all following of the User FID
async function fetchAllFollowings (fid) {
    const neynarBaseURL = "https://api.neynar.com/v2/farcaster/following"
    let cursor = "";
    let users = [];
    do {
        const urlFollowingQueryParams = `fid=${fid}&limit=100&cursor=${cursor}`
        const neynarUsersFollowingURL = `${neynarBaseURL}?${urlFollowingQueryParams}`
        const result = await fetch(neynarUsersFollowingURL, {
            headers: {
                'Content-Type': 'application/json',
                api_key: process.env.NEYNAR_API_KEY
            }
        })
        const resultResponse = await result.json()
        users = users.concat(resultResponse.users);
        cursor = resultResponse.next.cursor
        // console.log(cursor);
    } while (cursor !== "" && cursor !== null);

    const filteredUsersFollowing = users.map(element => element.user.fid)
    return filteredUsersFollowing
};

const usersFollowingArray = await fetchAllFollowings(USER_FID);
console.log('Step 3 Users Following: ', usersFollowingArray); // Array of FIDs that the user if following

Here sometimes if a user has a lot of followings, the response time can increase, We are actively working on a better and faster work around to this, but until then.

Step 4: Finding Users in your Extended Network who you aren't already following

From the previous two steps, we now possess two arrays of FIDs: one comprising our extended network and the other our following. In this step, we create an array called suggestedFollowFIDsArray. Essentially, it iterates through the first array, personalizedNetworkRankedArray, and checks if each FID is included in the second array, usersFollowingArray. If it isn't, then that FID is added to a new array, suggestedFollowFIDsArray.

// Step 4: Finding Users in your Extended Network who you aren't already following
function findSuggestedFollowFIDs (personalizedNetworkRankedArray, usersFollowingArray) {
    const suggestedFollows = [];
    for (let i = 0; i < personalizedNetworkRankedArray.length; i++) {
        if (!usersFollowingArray.includes(personalizedNetworkRankedArray[i])) {
            suggestedFollows.push(personalizedNetworkRankedArray[i])
        }
    }
    return suggestedFollows
}
const suggestedFollowFIDsArray = findSuggestedFollowFIDs(personalizedNetworkRankedArray, usersFollowingArray);
console.log(suggestedFollowFIDsArray)

Step 5: Finding User Information of the suggested follows

From the previous step, we now possess an array called suggestedFollowFIDsArray. To enable your client to display all their information, fetching all the necessary data is imperative. Neynars provides an endpoint, accessible here: Neynars User Bulk, which allows fetching bulk user information, catering to at most 100 users at a time.

We've developed a function called fetchUserInfoBulk, which accepts an array of FIDs, splits them into chunks of 100 to comply with Neynars' criteria, concatenates those chunks into a string, and forwards them to the Neynars API. The resulting responses are stored in the resultResponse array. This process is repeated for all the split chunks.

Executing this function yields a response stored in the variable named suggestedFollowUserInfo, which essentially represents an array containing information about all the suggested users.

async function fetchUserInfoBulk(fidsArray) {
    const chunkSize = 99;
    const neynarBaseURL = "https://api.neynar.com/v2/farcaster/user/bulk";

    let resultResponses = [];

    // Split the array into chunks of size 100
    for (let i = 0; i < fidsArray.length; i += chunkSize) {
        const chunk = fidsArray.slice(i, i + chunkSize);
        const suggestedFollowFIDsString = chunk.map(element => element).join(",");
        console.log(suggestedFollowFIDsString);
        const neynarUserInfoParams = `fids=${suggestedFollowFIDsString}`;
        const neynarUserInfoURL = `${neynarBaseURL}?${neynarUserInfoParams}`;

        const result = await fetch(neynarUserInfoURL, {
            headers: {
                'Content-Type': 'application/json',
                api_key: process.env.NEYNAR_API_KEY
            }
        });

        const resultResponse = await result.json();
        const resultResponseUsers = resultResponse.users;
        resultResponses.push(resultResponseUsers);
    }

    return resultResponses.flat(1);
}

const suggestedFollowUserInfo = await fetchUserInfoBulk(suggestedFollowFIDsArray);
console.log('Suggested Follow: ', suggestedFollowUserInfo);

Extending suggestions to also show on other user profile who you just followed.

Twitter and other popular platforms offer a feature wherein, upon following a user, they promptly display another suggested list of users to follow based on the followed user's network.

The aforementioned functions can be repurposed to create this functionality. The only adjustment required is to replace the network array (from Step 2) with the recently followed FID. Following this, all other steps can remain unchanged to generate this feature.

The current implementation of this is still slow, we are currently working with partners to optmize this and make it faster. The docs will be updated as and when it happens.

Last updated

Logo

Copyright 2024