MCP EVM Signer

  • src
import fetch from 'node-fetch'; // Interface for the compiler API response interface CompilerOutput { errors?: { type: string; severity: string; message: string; }[]; contracts?: { [fileName: string]: { [contractName: string]: { abi: any[]; evm: { bytecode: { object: string; }; }; }; }; }; } /** * Compile Solidity source code using a public API * (This uses a public endpoint but in production you might want to use a local solc compiler) */ export async function compileSolidity( source: string, contractName: string = 'Contract' ): Promise<{ abi: any[]; bytecode: string }> { // Prepare the JSON for the API request const input = { language: 'Solidity', sources: { 'main.sol': { content: source, }, }, settings: { outputSelection: { '*': { '*': ['abi', 'evm.bytecode'], }, }, optimizer: { enabled: true, runs: 200, }, }, }; // Make a request to the Solidity compiler API const response = await fetch('https://solc-bin.ethereum.org/api/compiler', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify(input), }); if (!response.ok) { throw new Error(`Compilation failed: ${response.statusText}`); } const output: CompilerOutput = await response.json(); // Check for compilation errors if (output.errors) { const errorMessages = output.errors .filter(error => error.severity === 'error') .map(error => error.message) .join('\n'); if (errorMessages) { throw new Error(`Compilation errors:\n${errorMessages}`); } } // Find the contract in the output if (!output.contracts || !output.contracts['main.sol']) { throw new Error('Compilation succeeded but no contracts found'); } // If the contract name is not specified, take the first contract const contracts = output.contracts['main.sol']; const contractKeys = Object.keys(contracts); if (contractKeys.length === 0) { throw new Error('No contracts found in the compiled output'); } // Try to find the named contract, or use the first one const compiledContract = contracts[contractName] || contracts[contractKeys[0]]; if (!compiledContract) { throw new Error(`Contract '${contractName}' not found in compilation output`); } return { abi: compiledContract.abi, bytecode: compiledContract.evm.bytecode.object, }; } /** * Extract function arguments from ABI and contract deployment parameters */ export function parseConstructorArgs(abi: any[], args: string): any[] { // Find the constructor in the ABI const constructor = abi.find(item => item.type === 'constructor'); if (!constructor || !constructor.inputs || constructor.inputs.length === 0) { // No constructor arguments needed return []; } // Parse the arguments string as JSON try { return JSON.parse(args); } catch (error) { throw new Error('Failed to parse constructor arguments. Must be a valid JSON array.'); } }