UNPKG

devion-mcp-server

Version:

MCP server for Devion blockchain infrastructure - AI-native blockchain data access for developers and AI agents

207 lines 8.07 kB
import { DevionSDK } from 'devion-sdk'; import { z } from 'zod'; import { SUPPORTED_NETWORKS } from '../types.js'; export const getLatestBlock = { name: 'get_latest_block', description: 'Get the latest block information including number, hash, timestamp, and gas data', inputSchema: { type: 'object', properties: { network: { type: 'string', enum: SUPPORTED_NETWORKS, description: 'Blockchain network to query (defaults to ethereum-mainnet)' }, include_transactions: { type: 'boolean', description: 'Include transaction hashes in the block data', default: false } }, required: [] }, async handler(args) { const schema = z.object({ network: z.enum(SUPPORTED_NETWORKS).default('ethereum-mainnet'), include_transactions: z.boolean().default(false) }); const { network, include_transactions } = schema.parse(args); const sdk = new DevionSDK({ apiKey: process.env.DEVION_API_KEY, baseURL: 'https://api.devion.dev', network: network }); try { const block = await sdk.rpc('eth_getBlockByNumber', ['latest', include_transactions]); if (!block) { return { success: false, error: 'Failed to fetch latest block', details: { network } }; } const blockData = { number: parseInt(block.number, 16), hash: block.hash, parent_hash: block.parentHash, timestamp: parseInt(block.timestamp, 16), timestamp_formatted: new Date(parseInt(block.timestamp, 16) * 1000).toISOString(), gas_limit: parseInt(block.gasLimit, 16), gas_used: parseInt(block.gasUsed, 16), gas_utilization: Math.round((parseInt(block.gasUsed, 16) / parseInt(block.gasLimit, 16)) * 100 * 100) / 100, transaction_count: Array.isArray(block.transactions) ? block.transactions.length : 0, miner: block.miner, difficulty: block.difficulty, total_difficulty: block.totalDifficulty }; const result = { success: true, data: { block: blockData, network, timestamp: new Date().toISOString() } }; if (include_transactions && Array.isArray(block.transactions)) { result.data.transactions = block.transactions.slice(0, 10); result.data.total_transactions = block.transactions.length; if (block.transactions.length > 10) { result.data.note = 'Only first 10 transactions shown for performance. Use get_transaction_details for specific transactions.'; } } return result; } catch (error) { return { success: false, error: error instanceof Error ? error.message : 'Unknown error occurred', details: { network, timestamp: new Date().toISOString() } }; } } }; export const getGasPrices = { name: 'get_gas_prices', description: 'Get current gas prices for one or multiple networks to help optimize transaction costs', inputSchema: { type: 'object', properties: { networks: { type: 'array', items: { type: 'string', enum: SUPPORTED_NETWORKS }, description: 'Array of networks to get gas prices for (defaults to all mainnet networks)', minItems: 1, maxItems: 6 }, include_estimates: { type: 'boolean', description: 'Include transaction cost estimates for common operations', default: false } }, required: [] }, async handler(args) { const schema = z.object({ networks: z.array(z.enum(SUPPORTED_NETWORKS)).default([ 'ethereum-mainnet', 'base-mainnet', 'arbitrum-mainnet', 'polygon-mainnet' ]), include_estimates: z.boolean().default(false) }); const { networks, include_estimates } = schema.parse(args); const results = []; const errors = []; for (const network of networks) { try { const apiKey = process.env.DEVION_API_KEY; if (!apiKey) { errors.push({ network: network, error: 'DEVION_API_KEY environment variable not set' }); continue; } const sdk = new DevionSDK({ apiKey: apiKey, baseURL: 'https://api.devion.dev', network: network }); const [gasPrice, blockNumber] = await Promise.all([ sdk.rpc('eth_gasPrice'), sdk.getBlockNumber() ]); const gasPriceWei = parseInt(gasPrice, 16); const gasPriceGwei = gasPriceWei / 1e9; const gasPriceData = { network, gas_price_wei: gasPriceWei, gas_price_gwei: Math.round(gasPriceGwei * 100) / 100, gas_price_formatted: `${Math.round(gasPriceGwei * 100) / 100} gwei`, block_number: typeof blockNumber === 'string' ? parseInt(blockNumber, 16) : blockNumber, timestamp: new Date().toISOString() }; results.push(gasPriceData); } catch (error) { errors.push({ network, error: error instanceof Error ? error.message : 'Unknown error' }); } } const response = { success: results.length > 0, data: { gas_prices: results, networks_queried: networks.length, successful_queries: results.length, failed_queries: errors.length, timestamp: new Date().toISOString() } }; if (include_estimates && results.length > 0) { response.data.estimates = { simple_transfer: results.map(gp => ({ network: gp.network, gas_limit: 21000, cost_gwei: Math.round(gp.gas_price_gwei * 21000 * 100) / 100, cost_eth: (gp.gas_price_gwei * 21000) / 1e9, cost_usd_estimate: ((gp.gas_price_gwei * 21000) / 1e9) * getEstimatedEthPrice(gp.network) })), erc20_transfer: results.map(gp => ({ network: gp.network, gas_limit: 65000, cost_gwei: Math.round(gp.gas_price_gwei * 65000 * 100) / 100, cost_eth: (gp.gas_price_gwei * 65000) / 1e9, cost_usd_estimate: ((gp.gas_price_gwei * 65000) / 1e9) * getEstimatedEthPrice(gp.network) })) }; } if (errors.length > 0) { response.data.errors = errors; } return response; } }; function getEstimatedEthPrice(network) { switch (network) { case 'ethereum-mainnet': case 'base-mainnet': case 'arbitrum-mainnet': return 2500; case 'polygon-mainnet': return 0.8; default: return 0; } } //# sourceMappingURL=blocks.js.map