Skip to main content
Glama

getWalletPnl

Calculate profit and loss for an Ethereum wallet by analyzing transaction history. Input the wallet address and chain to track financial performance and portfolio changes.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
addressYes
chainNoeth

Implementation Reference

  • The async handler function that executes the getWalletPnl tool logic. It uses the Moralis API via PowerShell to fetch wallet profitability data, processes the response to compute summary statistics like total invested, realized profit/loss, and counts of profitable/unprofitable tokens, then returns a formatted text response.
    async ({ address, chain }) => { try { // Use API key from environment variable const apiKey = process.env.MORALIS_API_KEY; if (!apiKey) { throw new Error("MORALIS_API_KEY environment variable is not set"); } // Format the URL for PowerShell request const url = `https://deep-index.moralis.io/api/v2.2/wallets/${address}/profitability?chain=${chain}`; const psCommand = `powershell -Command "Invoke-RestMethod -Method Get -Uri '${url}' -Headers @{'X-API-Key'='${apiKey}'; 'accept'='application/json'} | ConvertTo-Json -Depth 10"`; // Execute PowerShell command const { stdout } = await execPromise(psCommand); const response = JSON.parse(stdout); // Get profit/loss data from the response const tokens = response.result || []; // Process data - calculate some summary statistics let totalRealizedProfit = 0; let totalInvested = 0; let profitableTokens = 0; let unprofitableTokens = 0; tokens.forEach(token => { if (token.realized_profit_usd) { totalRealizedProfit += parseFloat(token.realized_profit_usd); } if (token.total_usd_invested) { totalInvested += parseFloat(token.total_usd_invested); } if (parseFloat(token.realized_profit_percentage || 0) > 0) { profitableTokens++; } else if (parseFloat(token.realized_profit_percentage || 0) < 0) { unprofitableTokens++; } }); return { content: [{ type: "text", text: `Wallet PnL for ${address} on chain ${chain}:\n` + `Summary: ${tokens.length} tokens analyzed\n` + `Total invested: $${totalInvested.toFixed(2)}\n` + `Total realized profit/loss: $${totalRealizedProfit.toFixed(2)}\n` + `Profitable tokens: ${profitableTokens}, Unprofitable tokens: ${unprofitableTokens}\n\n` + `Detailed results: ${JSON.stringify(tokens, null, 2)}` }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching wallet profitability: ${error.message}` }] }; } } );
  • Zod input schema validation for the tool: 'address' must be a valid Ethereum address (0x followed by 40 hex chars), 'chain' is optional string defaulting to 'eth'.
    { address: z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address"), chain: z.string().optional().default("eth") },
  • The registration of the 'getWalletPnl' tool via server.tool() within the exported registerProfitabilityTools function, including schema and handler.
    export function registerProfitabilityTools(server) { // Add wallet profitability tool server.tool("getWalletPnl", { address: z.string().regex(/^0x[a-fA-F0-9]{40}$/, "Invalid Ethereum address"), chain: z.string().optional().default("eth") }, async ({ address, chain }) => { try { // Use API key from environment variable const apiKey = process.env.MORALIS_API_KEY; if (!apiKey) { throw new Error("MORALIS_API_KEY environment variable is not set"); } // Format the URL for PowerShell request const url = `https://deep-index.moralis.io/api/v2.2/wallets/${address}/profitability?chain=${chain}`; const psCommand = `powershell -Command "Invoke-RestMethod -Method Get -Uri '${url}' -Headers @{'X-API-Key'='${apiKey}'; 'accept'='application/json'} | ConvertTo-Json -Depth 10"`; // Execute PowerShell command const { stdout } = await execPromise(psCommand); const response = JSON.parse(stdout); // Get profit/loss data from the response const tokens = response.result || []; // Process data - calculate some summary statistics let totalRealizedProfit = 0; let totalInvested = 0; let profitableTokens = 0; let unprofitableTokens = 0; tokens.forEach(token => { if (token.realized_profit_usd) { totalRealizedProfit += parseFloat(token.realized_profit_usd); } if (token.total_usd_invested) { totalInvested += parseFloat(token.total_usd_invested); } if (parseFloat(token.realized_profit_percentage || 0) > 0) { profitableTokens++; } else if (parseFloat(token.realized_profit_percentage || 0) < 0) { unprofitableTokens++; } }); return { content: [{ type: "text", text: `Wallet PnL for ${address} on chain ${chain}:\n` + `Summary: ${tokens.length} tokens analyzed\n` + `Total invested: $${totalInvested.toFixed(2)}\n` + `Total realized profit/loss: $${totalRealizedProfit.toFixed(2)}\n` + `Profitable tokens: ${profitableTokens}, Unprofitable tokens: ${unprofitableTokens}\n\n` + `Detailed results: ${JSON.stringify(tokens, null, 2)}` }] }; } catch (error) { return { content: [{ type: "text", text: `Error fetching wallet profitability: ${error.message}` }] }; } } ); }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/0xGval/evm-mcp-tools'

If you have feedback or need assistance with the MCP directory API, please join our Discord server