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
TableJSON 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 formatUserBalanceasync ({ 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.toolserver.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 APIasync 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 responsefunction 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; }