Skip to main content
Glama
dewanshparashar

Arbitrum MCP Server

nitro-node-client.ts13.2 kB
// Nitro Node specific information export interface NodeHealth { status: string; lastUpdated: string; error?: string; } export interface SyncStatus { currentBlock: number; highestBlock: number; isSyncing: boolean; syncProgress: number; error?: string; } export interface PeerInfo { id: string; name: string; caps: string[]; network: { localAddress: string; remoteAddress: string; }; protocols: Record<string, any>; } export interface BlockMetadata { blockNumber: number; metadata: string; // Raw metadata bytes as hex string } export interface ValidateBlockResult { valid: boolean; latency?: number; globalState?: any; error?: string; } export interface ValidationInputs { inputs: any; error?: string; } export interface MaintenanceStatus { secondsSinceLastMaintenance: number; error?: string; } export interface TraceResult { traces: any; error?: string; } export interface PublisherHealth { healthy: boolean; error?: string; } export class NitroNodeClient { private rpcUrl: string; constructor(rpcUrl: string) { this.rpcUrl = rpcUrl; } // ========== LEGACY NODE STATUS METHODS ========== // (Keeping for backwards compatibility) async getHealth(): Promise<NodeHealth> { try { const response = await this.makeRpcCall("arb_getHealth", []); return { status: response.status || "unknown", lastUpdated: new Date().toISOString(), }; } catch (error) { return { status: "unavailable", lastUpdated: new Date().toISOString(), error: "Health check not supported on this RPC endpoint. This method typically requires access to a node's admin API.", }; } } async getSyncStatus(): Promise<SyncStatus> { try { const syncResponse = await this.makeRpcCall("eth_syncing", []); const latestBlock = await this.makeRpcCall("eth_blockNumber", []); if (syncResponse === false) { return { currentBlock: parseInt(latestBlock, 16), highestBlock: parseInt(latestBlock, 16), isSyncing: false, syncProgress: 100, }; } const current = parseInt(syncResponse.currentBlock, 16); const highest = parseInt(syncResponse.highestBlock, 16); return { currentBlock: current, highestBlock: highest, isSyncing: true, syncProgress: highest > 0 ? (current / highest) * 100 : 0, }; } catch (error) { // Try to get at least the current block number as a fallback try { const latestBlock = await this.makeRpcCall("eth_blockNumber", []); const blockNum = parseInt(latestBlock, 16); return { currentBlock: blockNum, highestBlock: blockNum, isSyncing: false, syncProgress: 100, error: "Sync status not supported on this RPC endpoint. Showing current block number only.", }; } catch (blockError) { return { currentBlock: 0, highestBlock: 0, isSyncing: false, syncProgress: 0, error: "Sync status not supported on this RPC endpoint. This method typically requires access to a node's debug API.", }; } } } async getPeers(): Promise<PeerInfo[] | { error: string }> { try { const peers = await this.makeRpcCall("admin_peers", []); return peers.map((peer: any) => ({ id: peer.id, name: peer.name, caps: peer.caps, network: peer.network, protocols: peer.protocols, })); } catch (error) { return { error: "Peer information not supported on this RPC endpoint. This method typically requires access to a node's admin API.", }; } } // ========== CORE ARBITRUM METHODS (arb namespace) ========== async checkPublisherHealth(): Promise<PublisherHealth> { try { await this.makeRpcCall("arb_checkPublisherHealth", []); return { healthy: true, }; } catch (error) { return { healthy: false, error: `Publisher health check failed or not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async getRawBlockMetadata( fromBlock: number, toBlock: number ): Promise<BlockMetadata[] | { error: string }> { try { const result = await this.makeRpcCall("arb_getRawBlockMetadata", [ `0x${fromBlock.toString(16)}`, `0x${toBlock.toString(16)}`, ]); if (Array.isArray(result)) { return result.map((item: any) => ({ blockNumber: parseInt(item.blockNumber, 16), metadata: item.metadata || item.rawMetadata, })); } return { error: "Unexpected response format from arb_getRawBlockMetadata", }; } catch (error) { return { error: `Raw block metadata not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async getLatestValidated(): Promise<any> { try { return await this.makeRpcCall("arb_latestValidated", []); } catch (error) { return { error: `Latest validated state not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== TRACE METHODS (arbtrace namespace) ========== async traceCall( callArgs: any, traceTypes: string[], blockNumOrHash?: string ): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_call", [ callArgs, traceTypes, blockNumOrHash || "latest", ]); return { traces }; } catch (error) { return { traces: null, error: `Trace call not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async traceCallMany( calls: any[], blockNumOrHash?: string ): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_callMany", [ calls, blockNumOrHash || "latest", ]); return { traces }; } catch (error) { return { traces: null, error: `Trace callMany not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async replayBlockTransactions( blockNumOrHash: string, traceTypes: string[] ): Promise<TraceResult> { try { const traces = await this.makeRpcCall( "arbtrace_replayBlockTransactions", [blockNumOrHash, traceTypes] ); return { traces }; } catch (error) { return { traces: null, error: `Trace replayBlockTransactions not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async replayTransaction( txHash: string, traceTypes: string[] ): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_replayTransaction", [ txHash, traceTypes, ]); return { traces }; } catch (error) { return { traces: null, error: `Trace replayTransaction not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async traceTransaction(txHash: string): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_transaction", [txHash]); return { traces }; } catch (error) { return { traces: null, error: `Trace transaction not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async traceGet(txHash: string, path: string[]): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_get", [txHash, path]); return { traces }; } catch (error) { return { traces: null, error: `Trace get not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async traceBlock(blockNumOrHash: string): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_block", [blockNumOrHash]); return { traces }; } catch (error) { return { traces: null, error: `Trace block not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async traceFilter(filter: any): Promise<TraceResult> { try { const traces = await this.makeRpcCall("arbtrace_filter", [filter]); return { traces }; } catch (error) { return { traces: null, error: `Trace filter not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== DEBUG METHODS (arbdebug namespace) ========== async validateMessageNumber( msgNum: number, full: boolean = false, moduleRoot?: string ): Promise<ValidateBlockResult> { try { const params = [`0x${msgNum.toString(16)}`, full]; if (moduleRoot) { params.push(moduleRoot); } const result = await this.makeRpcCall( "arbdebug_validateMessageNumber", params ); return { valid: result.valid || true, latency: result.latency, globalState: result.globalState, }; } catch (error) { return { valid: false, error: `Validate message number not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async getValidationInputsAt( msgNum: number, target?: string ): Promise<ValidationInputs> { try { const params = [`0x${msgNum.toString(16)}`]; if (target) { params.push(target); } const inputs = await this.makeRpcCall( "arbdebug_validationInputsAt", params ); return { inputs }; } catch (error) { return { inputs: null, error: `Validation inputs not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== MAINTENANCE METHODS ========== async getMaintenanceStatus(): Promise<MaintenanceStatus> { try { const seconds = await this.makeRpcCall( "maintenance_secondsSinceLastMaintenance", [] ); return { secondsSinceLastMaintenance: typeof seconds === "number" ? seconds : parseInt(seconds, 10), }; } catch (error) { return { secondsSinceLastMaintenance: -1, error: `Maintenance status not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } async triggerMaintenance(): Promise<{ success: boolean; error?: string }> { try { await this.makeRpcCall("maintenance_trigger", []); return { success: true }; } catch (error) { return { success: false, error: `Trigger maintenance not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== TIMEBOOST METHODS ========== async sendExpressLaneTransaction( submission: any ): Promise<{ success: boolean; error?: string }> { try { await this.makeRpcCall("timeboost_sendExpressLaneTransaction", [ submission, ]); return { success: true }; } catch (error) { return { success: false, error: `Express lane transaction not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== AUCTIONEER METHODS ========== async submitAuctionResolutionTransaction( tx: any ): Promise<{ success: boolean; error?: string }> { try { await this.makeRpcCall("auctioneer_submitAuctionResolutionTransaction", [ tx, ]); return { success: true }; } catch (error) { return { success: false, error: `Auction resolution transaction not supported on this RPC endpoint: ${ (error as Error).message }`, }; } } // ========== UTILITY METHODS ========== private async makeRpcCall(method: string, params: any[]): Promise<any> { try { const requestBody = { jsonrpc: "2.0", id: Date.now(), method, params, }; console.error(`Making RPC call to ${this.rpcUrl}: ${method}`); const response = await fetch(this.rpcUrl, { method: "POST", headers: { "Content-Type": "application/json", }, body: JSON.stringify(requestBody), }); if (!response.ok) { throw new Error(`HTTP ${response.status}: ${response.statusText}`); } const data = await response.json(); if (data.error) { throw new Error(`RPC Error: ${data.error.message}`); } return data.result; } catch (error) { console.error(`RPC call failed for ${method} on ${this.rpcUrl}:`, error); if (error instanceof Error) { throw error; } else { throw new Error(`Unknown error during RPC call: ${String(error)}`); } } } }

Implementation Reference

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/dewanshparashar/arbitrum-mcp'

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