Skip to main content
Glama
getTransactionLogs.ts6.96 kB
import { ToolAnnotations } from "@modelcontextprotocol/sdk/types.js"; import { getDefaultProvider } from "@coti-io/coti-ethers"; import { getNetwork } from "../shared/account.js"; import { z } from "zod"; export const GET_TRANSACTION_LOGS: ToolAnnotations = { title: "Get Transaction Logs", name: "get_transaction_logs", description: "Get the logs from a transaction on the COTI blockchain. " + "This is used for retrieving event logs emitted during transaction execution. " + "Requires a transaction hash as input. " + "Returns detailed information about the transaction logs including event names, topics, and data.", inputSchema: { private_key: z.string().describe("Private key of the account (tracked by AI from previous operations)"), aes_key: z.string().optional().describe("AES key for private transactions (tracked by AI). Required for private operations."), network: z.enum(['testnet', 'mainnet']).describe("Network to use: 'testnet' or 'mainnet' (required)."), transaction_hash: z.string().describe("Transaction hash to get logs for"), }, }; /** * Checks if the input arguments are valid for the get_transaction_logs tool * @param args The input arguments to check * @returns True if the arguments are valid, false otherwise */ export function isGetTransactionLogsArgs(args: unknown): args is { transaction_hash: string , private_key?: string, aes_key?: string, network: 'testnet' | 'mainnet' } { return ( typeof args === "object" && args !== null && "transaction_hash" in args && typeof (args as any).transaction_hash === "string" ); } /** * Gets the logs from a transaction on the COTI blockchain * @param transaction_hash The hash of the transaction to get logs for * @returns An object with transaction logs and formatted text */ export async function performGetTransactionLogs(transaction_hash: string, network: 'testnet' | 'mainnet'): Promise<{ transactionHash: string, totalLogs: number, logs: Array<{ address: string, blockNumber: number, transactionIndex: number, logIndex: number | string, removed: boolean, topics: string[], data: string, eventSignature?: string }>, explorerUrl?: string, status: string, formattedText: string }> { try { const provider = getDefaultProvider(getNetwork(network)); let receipt; try { receipt = await provider.getTransactionReceipt(transaction_hash); } catch (error) { const formattedText = `Transaction Not Found or Pending\nTransaction Hash: ${transaction_hash}\nStatus: No logs available (Transaction may be pending or not found)`; return { transactionHash: transaction_hash, totalLogs: 0, logs: [], status: 'Not Found or Pending', formattedText }; } if (!receipt) { const formattedText = `Transaction Not Found or Pending\nTransaction Hash: ${transaction_hash}\nStatus: No logs available (Transaction may be pending or not found)`; return { transactionHash: transaction_hash, totalLogs: 0, logs: [], status: 'Not Found or Pending', formattedText }; } const logs = receipt.logs; if (!logs || logs.length === 0) { const formattedText = `Transaction Hash: ${transaction_hash}\n\nNo logs found for this transaction.`; return { transactionHash: transaction_hash, totalLogs: 0, logs: [], status: 'No Logs', formattedText }; } const explorerUrl = `https://${network === 'mainnet' ? 'mainnet' : 'testnet'}.cotiscan.io/tx/${transaction_hash}`; let formattedText = `Transaction Hash: ${transaction_hash}\n\n`; formattedText += `Total Logs: ${logs.length}\n\n`; const logsData = logs.map((log, index) => { formattedText += `Log #${index + 1}:\n`; formattedText += ` Address: ${log.address}\n`; formattedText += ` Block Number: ${log.blockNumber}\n`; formattedText += ` Transaction Index: ${log.transactionIndex}\n`; formattedText += ` Log Index: ${log.index !== undefined ? log.index : 'N/A'}\n`; formattedText += ` Removed: ${log.removed !== undefined ? log.removed : 'false'}\n`; formattedText += ` Topics (${log.topics.length}):\n`; log.topics.forEach((topic, topicIndex) => { formattedText += ` Topic ${topicIndex}: ${topic}\n`; }); formattedText += ` Data: ${log.data}\n\n`; let eventSignature: string | undefined; if (log.topics.length > 0) { eventSignature = log.topics[0]; formattedText += ` Event Signature: ${eventSignature}\n\n`; } return { address: log.address, blockNumber: log.blockNumber, transactionIndex: log.transactionIndex, logIndex: log.index !== undefined ? log.index : 'N/A', removed: log.removed !== undefined ? log.removed : false, topics: [...log.topics], data: log.data, eventSignature }; }); formattedText += `View on Explorer: ${explorerUrl}\n`; return { transactionHash: transaction_hash, totalLogs: logs.length, logs: logsData, explorerUrl, status: 'Success', formattedText }; } catch (error) { console.error('Error getting transaction logs:', error); throw new Error(`Failed to get transaction logs: ${error instanceof Error ? error.message : String(error)}`); } } /** * Handler for the getTransactionLogs tool * @param args The arguments for the tool * @returns The tool response */ export async function getTransactionLogsHandler(args: any): Promise<any> { if (!isGetTransactionLogsArgs(args)) { throw new Error("Invalid arguments for get_transaction_logs"); } const { transaction_hash, network, private_key, aes_key } = args; const results = await performGetTransactionLogs(transaction_hash, network); return { structuredContent: { transactionHash: results.transactionHash, totalLogs: results.totalLogs, logs: results.logs, explorerUrl: results.explorerUrl, status: results.status }, content: [{ type: "text", text: results.formattedText }], isError: false, }; }

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/davibauer/coti-mcp'

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