getLighthousePortfolio
Fetch and display a detailed summary of your Lighthouse crypto portfolio, including asset type breakdowns and major holdings, for informed decision-making.
Instructions
Fetch and display a detailed summary of a Lighthouse portfolio with breakdown by asset types and major holdings.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| portfolio | No | Optional portfolio name to select a specific portfolio to display a summary for |
Implementation Reference
- index.ts:99-227 (registration)Registration of the 'getLighthousePortfolio' tool using server.addTool, including name, description, Zod schema for parameters, and the execute handler function.server.addTool({ name: "getLighthousePortfolio", description: "Fetch and display a detailed summary of a Lighthouse portfolio with breakdown by asset types and major holdings.", parameters: z.object({ portfolio: z .string() .optional() .describe( "Optional portfolio name to select a specific portfolio to display a summary for" ), }), execute: async (args) => { try { if (!lighthouse.isAuthenticated()) { return { content: [ { type: "text", text: "No session cookie available. Please authenticate first.", }, ], }; } // Find the portfolio const portfolio = await lighthouse.findPortfolio(args.portfolio); // Get the portfolio data const data = await lighthouse.getPortfolioData(portfolio.slug); // Calculate total USD value const totalUsdValue = data.usdValue; // Get wallets/accounts const wallets = Object.values(data.accounts).map((account: Account) => ({ id: account.id, name: account.name, type: account.type, })); // Calculate asset type breakdown const assetTypeMap = new Map<string, number>(); data.positions.forEach((position: Position) => { position.assets.forEach((asset: LighthouseAsset) => { const currentValue = assetTypeMap.get(asset.type) || 0; assetTypeMap.set(asset.type, currentValue + asset.usdValue); }); }); // Convert to array and sort by value const assetTypeBreakdown = Array.from(assetTypeMap.entries()) .map(([type, value]) => ({ type, value, percentage: (value / totalUsdValue) * 100, })) .sort((a, b) => b.value - a.value); // Get major assets (>= $1000) const majorAssets = data.positions .flatMap((position) => position.assets .filter((asset) => asset.usdValue >= 1000) .map((asset) => ({ name: asset.name, symbol: asset.symbol, value: asset.usdValue, amount: asset.amount, })) ) .sort((a, b) => b.value - a.value); // Format the response const assetTypeTable = ` | Asset Type | Net Value | % of Portfolio | |------------|-----------|----------------| ${assetTypeBreakdown .map( (item) => `| ${item.type} | $${formatNumber(item.value)} | ${formatPercentage( item.percentage )}% |` ) .join("\n")} `; const assetsTable = ` | Asset | Value | Amount | |-------|-------|--------| ${majorAssets .map( (asset) => `| ${asset.name} (${asset.symbol}) | $${formatNumber( asset.value )} | ${formatNumber(asset.amount)} |` ) .join("\n")} `; return { content: [ { type: "text", text: `# Lighthouse Portfolio Summary: ${ portfolio.name }\n\n## Total Portfolio Value: $${formatNumber( totalUsdValue )}\n\n## Wallets (${wallets.length}):\n${wallets .map((w) => `- ${w.name} (${w.type})`) .join( "\n" )}\n\n## Asset Type Breakdown:\n${assetTypeTable}\n\n## Major Holdings (>= $1,000):\n${assetsTable}`, }, ], }; } catch (error: any) { return { content: [ { type: "text", text: `Failed to fetch Lighthouse portfolio: ${error.message}`, }, ], }; } }, });
- index.ts:111-226 (handler)The execute handler that implements the core logic: authenticates, fetches portfolio data using lighthouse client, computes asset breakdowns and major holdings, formats tables, and returns markdown summary.execute: async (args) => { try { if (!lighthouse.isAuthenticated()) { return { content: [ { type: "text", text: "No session cookie available. Please authenticate first.", }, ], }; } // Find the portfolio const portfolio = await lighthouse.findPortfolio(args.portfolio); // Get the portfolio data const data = await lighthouse.getPortfolioData(portfolio.slug); // Calculate total USD value const totalUsdValue = data.usdValue; // Get wallets/accounts const wallets = Object.values(data.accounts).map((account: Account) => ({ id: account.id, name: account.name, type: account.type, })); // Calculate asset type breakdown const assetTypeMap = new Map<string, number>(); data.positions.forEach((position: Position) => { position.assets.forEach((asset: LighthouseAsset) => { const currentValue = assetTypeMap.get(asset.type) || 0; assetTypeMap.set(asset.type, currentValue + asset.usdValue); }); }); // Convert to array and sort by value const assetTypeBreakdown = Array.from(assetTypeMap.entries()) .map(([type, value]) => ({ type, value, percentage: (value / totalUsdValue) * 100, })) .sort((a, b) => b.value - a.value); // Get major assets (>= $1000) const majorAssets = data.positions .flatMap((position) => position.assets .filter((asset) => asset.usdValue >= 1000) .map((asset) => ({ name: asset.name, symbol: asset.symbol, value: asset.usdValue, amount: asset.amount, })) ) .sort((a, b) => b.value - a.value); // Format the response const assetTypeTable = ` | Asset Type | Net Value | % of Portfolio | |------------|-----------|----------------| ${assetTypeBreakdown .map( (item) => `| ${item.type} | $${formatNumber(item.value)} | ${formatPercentage( item.percentage )}% |` ) .join("\n")} `; const assetsTable = ` | Asset | Value | Amount | |-------|-------|--------| ${majorAssets .map( (asset) => `| ${asset.name} (${asset.symbol}) | $${formatNumber( asset.value )} | ${formatNumber(asset.amount)} |` ) .join("\n")} `; return { content: [ { type: "text", text: `# Lighthouse Portfolio Summary: ${ portfolio.name }\n\n## Total Portfolio Value: $${formatNumber( totalUsdValue )}\n\n## Wallets (${wallets.length}):\n${wallets .map((w) => `- ${w.name} (${w.type})`) .join( "\n" )}\n\n## Asset Type Breakdown:\n${assetTypeTable}\n\n## Major Holdings (>= $1,000):\n${assetsTable}`, }, ], }; } catch (error: any) { return { content: [ { type: "text", text: `Failed to fetch Lighthouse portfolio: ${error.message}`, }, ], }; } },
- index.ts:103-110 (schema)Zod schema defining the input parameters for the tool, with an optional 'portfolio' string.parameters: z.object({ portfolio: z .string() .optional() .describe( "Optional portfolio name to select a specific portfolio to display a summary for" ), }),