Skip to content

Commit

Permalink
[lib] use v2 relevant followers API to find farcaster friends
Browse files Browse the repository at this point in the history
Summary: this API returns what we want -- farcaster mutuals. and it seems to work pretty consistently, unlike the paginated v1 followers API.

Test Plan: successfully got back farcaster mutuals for dwr.eth (fid 3), who has a ton of followers

Reviewers: ashoat, will

Reviewed By: ashoat, will

Subscribers: tomek

Differential Revision: https://phab.comm.dev/D13530
  • Loading branch information
vdhanan committed Oct 1, 2024
1 parent 001e725 commit 288f984
Showing 1 changed file with 35 additions and 51 deletions.
86 changes: 35 additions & 51 deletions lib/utils/neynar-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,17 @@
import invariant from 'invariant';

import { getMessageForException } from './errors.js';
import type {
NeynarChannel,
NeynarUser,
NeynarUserWithViewerContext,
} from '../types/farcaster-types.js';

type FetchFollowersResponse = {
+result: {
+users: $ReadOnlyArray<NeynarUserWithViewerContext>,
+next: {
+cursor: ?string,
import type { NeynarChannel, NeynarUser } from '../types/farcaster-types.js';

type FetchRelevantFollowersResponse = {
+all_relevant_followers_dehydrated: $ReadOnlyArray<{
+user: {
+fid: number,
...
},
},
...
}>,
...
};

type FetchFarcasterChannelsResponse = {
Expand Down Expand Up @@ -60,7 +58,6 @@ function getNeynarURL(
return `${neynarURL}${apiCall}?${new URLSearchParams(params).toString()}`;
}

const fetchFollowerLimit = 150;
const fetchFollowedChannelsLimit = 100;
const fetchChannelsLimit = 50;

Expand All @@ -73,48 +70,35 @@ class NeynarClient {

// We're using the term "friend" for a bidirectional follow
async fetchFriendFIDs(fid: string): Promise<string[]> {
const fids = [];
let paginationCursor = null;

do {
const params: { [string]: string } = {
fid,
viewerFid: fid,
limit: fetchFollowerLimit.toString(),
...(paginationCursor ? { cursor: paginationCursor } : null),
};

const url = getNeynarURL('1', 'followers', params);

try {
const response = await fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
api_key: this.apiKey,
},
});
const params: { [string]: string } = {
target_fid: fid,
viewer_fid: fid,
};

const json: FetchFollowersResponse = await response.json();
const { users } = json.result;
const url = getNeynarURL('2', 'followers/relevant', params);

for (const user of users) {
if (user.viewerContext.following) {
fids.push(user.fid.toString());
}
}
try {
const response = await fetch(url, {
method: 'GET',
headers: {
Accept: 'application/json',
api_key: this.apiKey,
},
});

paginationCursor = json.result.next.cursor;
} catch (error) {
console.log(
'Failed to fetch friend FIDs:',
getMessageForException(error) ?? 'unknown',
);
throw error;
}
} while (paginationCursor);
const json: FetchRelevantFollowersResponse = await response.json();
const { all_relevant_followers_dehydrated } = json;

return fids;
return all_relevant_followers_dehydrated.map(follower =>
follower.user.fid.toString(),
);
} catch (error) {
console.log(
'Failed to fetch friend FIDs:',
getMessageForException(error) ?? 'unknown',
);
throw error;
}
}

async fetchFollowedFarcasterChannelsWithFilter(
Expand Down

0 comments on commit 288f984

Please sign in to comment.