Created
January 28, 2025 13:10
-
-
Save anastasiarods/711afbb8273dd2354a6e7afd8525a5cd to your computer and use it in GitHub Desktop.
Get Farcaster User Data
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createPublicClient, http } from "viem"; | |
import { base, optimism } from "viem/chains"; | |
const HUB_URL = "https://hub.pinata.cloud"; | |
const CONTRACTS = { | |
NEYNAR: "0xdB1eCF22d195dF9e03688C33707b19C68BdEd142", | |
REGISTRY: "0x00000000Fc6c5F01Fc30151999387Bb99A9f489b" | |
} as const; | |
interface User { | |
fid: number; | |
username: string; | |
display_name: string; | |
pfp_url: string; | |
profile: { | |
bio?: { text: string }; | |
location?: { latitude: number; longitude: number }; | |
}; | |
verified_accounts: { platform: string; username: string }[]; | |
verified_addresses: { | |
eth_addresses?: string[]; | |
sol_addresses?: string[]; | |
}; | |
custody_address: string; | |
} | |
async function fetchUserData(fid: number, type: number): Promise<string> { | |
const response = await fetch(`${HUB_URL}/v1/userDataByFid?fid=${fid}&user_data_type=${type}`); | |
const data = await response.json(); | |
return data?.data?.userDataBody?.value || ""; | |
} | |
async function fetchVerifications(fid: number) { | |
const response = await fetch(`${HUB_URL}/v1/verificationsByFid?fid=${fid}`); | |
const data = await response.json(); | |
return data?.messages || []; | |
} | |
async function getCustodyAddress(fid: number): Promise<string> { | |
const client = createPublicClient({ | |
chain: optimism, | |
transport: http() | |
}); | |
return client.readContract({ | |
address: CONTRACTS.REGISTRY, | |
abi: [{ | |
name: "custodyOf", | |
type: "function", | |
stateMutability: "view", | |
inputs: [{ name: "fid", type: "uint256" }], | |
outputs: [{ name: "custody", type: "address" }] | |
}], | |
functionName: "custodyOf", | |
args: [BigInt(fid)] | |
}); | |
} | |
export async function getUserByFid(fid: number): Promise<User> { | |
const [pfp, display, bio, username, location, twitter, verifications, custody] = await Promise.all([ | |
fetchUserData(fid, 1), // PFP | |
fetchUserData(fid, 2), // Display Name | |
fetchUserData(fid, 3), // Bio | |
fetchUserData(fid, 6), // Username | |
fetchUserData(fid, 7), // Location | |
fetchUserData(fid, 8), // Twitter | |
fetchVerifications(fid), | |
getCustodyAddress(fid) | |
]); | |
// Parse location if available | |
let locationData = undefined; | |
if (location?.startsWith("geo:")) { | |
const [lat, lng] = location.substring(4).split(","); | |
locationData = { latitude: parseFloat(lat), longitude: parseFloat(lng) }; | |
} | |
// Group verifications by protocol | |
const eth_addresses = verifications | |
.filter((msg: any) => msg.data.verificationAddAddressBody.protocol === "PROTOCOL_ETHEREUM") | |
.map((msg: any) => msg.data.verificationAddAddressBody.address); | |
const sol_addresses = verifications | |
.filter((msg: any) => msg.data.verificationAddAddressBody.protocol === "PROTOCOL_SOLANA") | |
.map((msg: any) => msg.data.verificationAddAddressBody.address); | |
return { | |
fid, | |
username: username || "", | |
display_name: display || "", | |
pfp_url: pfp, | |
profile: { | |
bio: bio ? { text: bio } : undefined, | |
location: locationData | |
}, | |
verified_accounts: twitter ? [{ platform: "x", username: twitter }] : [], | |
verified_addresses: { eth_addresses, sol_addresses }, | |
custody_address: custody | |
}; | |
} | |
export async function getUserByAddress(address: string): Promise<User> { | |
const client = createPublicClient({ | |
chain: base, | |
transport: http() | |
}); | |
const fid = await client.readContract({ | |
address: CONTRACTS.NEYNAR, | |
abi: [{ | |
name: "getFid", | |
type: "function", | |
stateMutability: "view", | |
inputs: [{ name: "verifier", type: "address" }], | |
outputs: [{ name: "fid", type: "uint256" }] | |
}], | |
functionName: "getFid", | |
args: [address as `0x${string}`] | |
}); | |
if (fid === BigInt(0)) throw new Error("User not found"); | |
return getUserByFid(Number(fid)); | |
} | |
getUserByAddress("0xd7029bdea1c17493893aafe29aad69ef892b8ff2").then((data) => { | |
console.log(data); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment