get-user-balance
Retrieve user balances from social platforms (Farcaster, Twitter, Telegram) by providing platform type and user ID. Integrates with MCP server for standardized social and onchain data access.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| platform | Yes | Social platform (farcaster, twitter, telegram) | |
| userId | Yes | Farcaster ID (FID) or username of the user |
Implementation Reference
- src/mcp/tools/contentTools.ts:440-486 (handler)MCP tool handler for get-user-balance: checks for farcaster platform, calls provider.getUserBalance(userId), formats result with formatUserBalance
async ({ platform, userId }) => { // Check if platform is Farcaster if (platform !== 'farcaster') { return { content: [{ type: "text", text: "User balance functionality is currently only supported for Farcaster." }], isError: true }; } try { // Get the provider for the platform const provider = providerRegistry.getProviderForPlatform(platform); if (!provider) { return { content: [{ type: "text", text: `Provider not found for platform: ${platform}` }], isError: true }; } // Get user balance (now accepts either FID or username) const balance = await provider.getUserBalance?.(userId); // Format the balance information return { content: [{ type: "text", text: formatUserBalance(balance) }] }; } catch (error) { console.error('Error fetching user balance:', error); return { content: [{ type: "text", text: `Failed to fetch user balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); - Zod input schema defining platform and userId parameters for the tool
{ platform: z.string().describe("Social platform (farcaster, twitter, telegram)"), userId: z.string().describe("Farcaster ID (FID) or username of the user") }, - src/mcp/tools/contentTools.ts:434-486 (registration)Registration of the get-user-balance tool in registerContentTools function using server.tool
server.tool( "get-user-balance", { platform: z.string().describe("Social platform (farcaster, twitter, telegram)"), userId: z.string().describe("Farcaster ID (FID) or username of the user") }, async ({ platform, userId }) => { // Check if platform is Farcaster if (platform !== 'farcaster') { return { content: [{ type: "text", text: "User balance functionality is currently only supported for Farcaster." }], isError: true }; } try { // Get the provider for the platform const provider = providerRegistry.getProviderForPlatform(platform); if (!provider) { return { content: [{ type: "text", text: `Provider not found for platform: ${platform}` }], isError: true }; } // Get user balance (now accepts either FID or username) const balance = await provider.getUserBalance?.(userId); // Format the balance information return { content: [{ type: "text", text: formatUserBalance(balance) }] }; } catch (error) { console.error('Error fetching user balance:', error); return { content: [{ type: "text", text: `Failed to fetch user balance: ${error instanceof Error ? error.message : String(error)}` }], isError: true }; } } ); - FarcasterProvider.getUserBalance implementation: resolves user FID, fetches balance from Neynar API
async getUserBalance(userId: string | number): Promise<any> { // Check if API key is provided if (!config.providers.farcaster.neynarApiKey) { console.error('Cannot get Farcaster user balance: No API key provided'); throw new Error('Cannot get Farcaster user balance: No API key provided. Please set NEYNAR_API_KEY in your .env file.'); } try { let fid: number; // Check if userId is a numeric FID or a username if (typeof userId === 'number' || /^\d+$/.test(String(userId))) { // If userId is numeric, parse it as FID fid = typeof userId === 'number' ? userId : parseInt(String(userId), 10); console.error(`Treating ${userId} as numeric FID: ${fid}`); } else { // If userId is not numeric, try to fetch by username console.error(`Treating ${userId} as username, looking up user`); try { // Use searchUser for username lookups const userResponse = await this.client.searchUser({ q: String(userId), limit: 1 }); if (!userResponse || !userResponse.result || !userResponse.result.users || !Array.isArray(userResponse.result.users) || userResponse.result.users.length === 0) { throw new Error(`User not found: ${userId}`); } const user = userResponse.result.users[0]; if (!user || !user.fid) { throw new Error(`User not found: ${userId}`); } fid = user.fid; console.error(`Found FID ${fid} for username ${userId}`); } catch (error) { console.error(`Error looking up user by username: ${error}`); throw new Error(`Failed to find user: ${userId}`); } } console.error(`Fetching user balance for FID: ${fid}`); // Make the API call to fetch user balance const response = await this.client.fetchUserBalance({ fid: fid, networks: ['base'] // Currently, only 'base' is supported }); console.error(`Response received: ${response ? 'Yes' : 'No'}`); if (!response || !response.user_balance) { console.error('No balance data found in response'); throw new Error('No balance data found for user'); } // Return the user_balance object directly return response.user_balance; } catch (error) { console.error('Error fetching user balance:', error); throw error; } } - formatUserBalance helper: formats raw balance data into readable text output for the tool response
function formatUserBalance(balance: any): string { if (!balance) { return "No balance information available."; } const addressBalances = balance.address_balances || []; if (addressBalances.length === 0) { return "No verified addresses found for this user."; } let formattedText = "User Balance Information:\n"; addressBalances.forEach((addrBalance: any) => { const verifiedAddress = addrBalance.verified_address; const tokenBalances = addrBalance.token_balances || []; formattedText += `\nBase Network Address: ${verifiedAddress.address}\n`; formattedText += "Token Balances:\n"; if (tokenBalances.length === 0) { formattedText += "- No token balances found\n"; } else { tokenBalances.forEach((tokenBalance: any) => { const token = tokenBalance.token; const balance = tokenBalance.balance; formattedText += `- ${token.symbol}: ${balance.in_token.toFixed(4)} (≈ $${balance.in_usdc.toFixed(2)} USDC)\n`; }); } }); formattedText += `\nLast Updated: ${new Date().toLocaleString()}`; return formattedText; }