Skip to main content
Glama

MCP Ethers Wallet

contractTests.ts6.57 kB
/** * @file Contract Tests * @version 1.0.0 * @status IN_DEVELOPMENT * @lastModified 2024-07-05 * * Tests for contract-related MCP tools * * IMPORTANT: * - Tests contract interaction through MCP protocol * - Validates contract responses * * Functionality: * - Tests getContractCode * - Tests contract call methods */ import { McpStandardClient } from '../../client/mcpStandardClient.js'; import { assert, assertDefined, assertToolSuccess } from '../../client/utils/assertions.js'; import { logger } from '../../../utils/logger.js'; // Well-known contract addresses for testing read-only calls const TEST_CONTRACTS = { // USDC contract on Ethereum mainnet usdc: '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48', // WETH contract on Ethereum mainnet weth: '0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2', // OpenSea Seaport contract seaport: '0x00000000006c3852cbEf3e08E8dF289169EdE581' }; // Simple ABI snippets for testing const USDC_ABI = '[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"}]'; /** * Get the list of contract-related tests * * @param client The MCP client to use for testing * @returns Array of test cases */ export function getContractTests(client: McpStandardClient): Array<{ name: string; test: () => Promise<void> }> { return [ { name: 'Get contract code', test: async () => { const result = await client.callTool('getContractCode', { address: TEST_CONTRACTS.usdc }); assertToolSuccess(result, 'Failed to get contract code'); // Find the text content in the response const codeText = result.content.find((item: any) => item.type === 'text')?.text; assertDefined(codeText, 'Contract code response has no text content'); // Verify the response contains contract bytecode (starts with 0x) assert( codeText.includes('0x'), `Contract code response does not contain bytecode` ); // Contract bytecode should be fairly long assert( codeText.length > 100, `Contract code response is too short to be valid bytecode` ); logger.debug('Contract code response length', { length: codeText.length }); } }, { name: 'Read USDC contract name', test: async () => { const result = await client.callTool('contractCall', { contractAddress: TEST_CONTRACTS.usdc, abi: USDC_ABI, method: 'name', args: [] }); assertToolSuccess(result, 'Failed to call contract name method'); // Find the text content in the response const nameText = result.content.find((item: any) => item.type === 'text')?.text; assertDefined(nameText, 'Contract name response has no text content'); // USDC's name should be "USD Coin" or similar assert( nameText.toLowerCase().includes('usd') && nameText.toLowerCase().includes('coin'), `Contract name response does not contain expected USDC name: ${nameText}` ); logger.debug('USDC contract name', { nameText }); } }, { name: 'Read USDC contract symbol', test: async () => { const result = await client.callTool('contractCall', { contractAddress: TEST_CONTRACTS.usdc, abi: USDC_ABI, method: 'symbol', args: [] }); assertToolSuccess(result, 'Failed to call contract symbol method'); // Find the text content in the response const symbolText = result.content.find((item: any) => item.type === 'text')?.text; assertDefined(symbolText, 'Contract symbol response has no text content'); // USDC's symbol should be "USDC" assert( symbolText.includes('USDC'), `Contract symbol response does not contain expected USDC symbol: ${symbolText}` ); logger.debug('USDC contract symbol', { symbolText }); } }, { name: 'Read USDC contract decimals', test: async () => { const result = await client.callTool('contractCall', { contractAddress: TEST_CONTRACTS.usdc, abi: USDC_ABI, method: 'decimals', args: [] }); assertToolSuccess(result, 'Failed to call contract decimals method'); // Find the text content in the response const decimalsText = result.content.find((item: any) => item.type === 'text')?.text; assertDefined(decimalsText, 'Contract decimals response has no text content'); // USDC's decimals should be 6 assert( decimalsText.includes('6'), `Contract decimals response does not contain expected USDC decimals (6): ${decimalsText}` ); logger.debug('USDC contract decimals', { decimalsText }); } }, { name: 'Read balance of address on USDC contract', test: async () => { // Check Vitalik's USDC balance const vitalikAddress = '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045'; const result = await client.callTool('contractCall', { contractAddress: TEST_CONTRACTS.usdc, abi: USDC_ABI, method: 'balanceOf', args: [vitalikAddress] }); assertToolSuccess(result, 'Failed to call contract balanceOf method'); // Find the text content in the response const balanceText = result.content.find((item: any) => item.type === 'text')?.text; assertDefined(balanceText, 'Contract balanceOf response has no text content'); // The balance should be a number assert( /\d/.test(balanceText), `Contract balanceOf response does not contain a numeric value: ${balanceText}` ); logger.debug(`USDC balance for ${vitalikAddress}`, { balanceText }); } } ]; }

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/crazyrabbitLTC/mcp-ethers-server'

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