app.ts
Overview
`app.ts` implements the core API server for the **Optimism** blockchain, leveraging Express.js for REST endpoints and WebSocket connections for real-time event streaming. It acts as a bridge between client applications and the Optimism blockchain indexer (via Blockbook WebSocket API), providing:
RESTful API endpoints for health checks, metrics, and blockchain data access (registered dynamically via
RegisterRoutes).WebSocket server to manage client subscriptions and push live blockchain updates (new blocks and transactions).
Integration with blockchain indexers (Blockbook) through WebSocket client to receive and process blockchain events.
Centralized event handling with
Registryfor dispatching updates to subscribed clients.Prometheus metrics integration to monitor server health and performance.
Swagger UI documentation for interactive API exploration.
This file orchestrates the server lifecycle, middleware setup, API routing, WebSocket event handling, and interaction with the blockchain data services specifically tailored to Optimism's EVM-compatible chain.
Detailed Explanation
Constants and Environment Variables
Name | Description |
|---|---|
`PORT` | Server listening port (default 3000 if not set) |
`INDEXER_WS_URL` | WebSocket URL of the blockchain indexer service (must be set) |
`INDEXER_API_KEY` | Optional API key for authenticating with the indexer |
`IS_LIQUIFY` | Boolean flag indicating if the indexer URL contains "liquify" |
`IS_NOWNODES` | Boolean flag indicating if the indexer URL contains "nownodes" |
Logger
`logger` is an instance of `Logger` configured with namespaces relevant to the Optimism API stack. It manages structured logging throughout the server.
Prometheus Metrics
`prometheus` collects metrics tagged with the chain identifier `"optimism"`. It exposes metrics via `/metrics` endpoint for monitoring.
Express Application Setup (app)
Uses common middleware from
@shapeshiftoss/common-apiproviding logging, JSON parsing, and Prometheus integration.Defines health check endpoint
/healthreturning server and connection status.Defines
/metricsendpoint serving Prometheus metrics.Serves static files for Swagger UI assets and JSON spec.
Mounts Swagger UI at
/docswith custom branding.Registers dynamic API routes via
RegisterRoutes(app).Redirects root
/to/docsfor API documentation access.Applies middleware for error handling and 404 not found.
Blockchain Event Handlers
These handlers process incoming blockchain data from the WebSocket client connected to the Blockbook indexer.
addressFormatter
const addressFormatter: AddressFormatter = (address) => evm.formatAddress(address)
Formats EVM addresses to a standardized form using utilities from
@shapeshiftoss/common-api.
blockHandler
const blockHandler: BlockHandler<NewBlock, Array<{ addresses: Array<string>; tx: evm.Tx }>> = async (block) => { ... }
Input:
blockof typeNewBlockrepresenting a newly observed blockchain block.Functionality:
Fetches block transactions using
service.handleBlock(block.hash).Fetches internal transactions for debugging with
service.fetchInternalTxsByBlockDebug(block.hash).Processes each transaction combining external and internal transactions.
Extracts all addresses involved in the transactions (both from blockbook and internal).
Output: Returns an object with the
txsarray containing{ addresses, tx }pairs.Usage: Registered with the
Registryto handle new block events.
transactionHandler
const transactionHandler: TransactionHandler<BlockbookTx, evm.Tx> = async (blockbookTx) => { ... }
Input: A single Blockbook transaction (
BlockbookTx).Functionality:
Processes transaction with internal tracing by calling
service.handleTransactionWithInternalTrace.Extracts addresses from both the transaction and its internal transactions.
Output: Object containing
addressesand the processed transactiontx.Usage: Registered with the
Registryfor handling individual transaction events.
Registry Initialization
const registry = new Registry({ addressFormatter, blockHandler, transactionHandler })
The
Registrymanages subscriptions associated with blockchain addresses and dispatches relevant blockchain events to subscribed WebSocket clients.It uses the above handlers and address formatting logic.
Blockbook WebSocket Client Setup
const blockbook = new WebsocketClient(wsUrl, {
apiKey,
blockHandler: [registry.onBlock.bind(registry), gasOracle.onBlock.bind(gasOracle)],
transactionHandler: registry.onTransaction.bind(registry),
})
Connects to the blockchain indexer WebSocket endpoint (
wsUrl), optionally attaching an API key.Registers multiple block handlers:
The registry's
onBlockmethod to process and dispatch block events.The
gasOracle.onBlockmethod to update gas price estimations.
Registers the registry's
onTransactionmethod for transaction events.
HTTP Server and WebSocket Server
const server = app.listen(PORT, () => logger.info('Server started'))
const wsServer = new Server({ server })
Starts the Express HTTP server on the configured port.
Creates a WebSocket server attached to the same HTTP server.
WebSocket Connection Handling
wsServer.on('connection', (connection) => {
ConnectionHandler.start(connection, registry, blockbook, prometheus, logger)
})
On each new client connection:
ConnectionHandler.startmanages the lifecycle of the WebSocket connection.Registers the connection with the
registryto handle subscriptions.Integrates with the
blockbookclient to receive blockchain events.Monitors metrics and logs connection activity.
Important Implementation Details
Dual block handlers: The design allows multiple handlers (
registryandgasOracle) to process the same block event asynchronously.Internal transaction tracing: Ethereum-like internal transactions enrich the blockchain data, improving the accuracy and detail of notifications.
Address deduplication: Address lists are carefully merged and deduplicated to optimize subscription management.
Dynamic WebSocket URL construction: The WebSocket URL and API key usage depend on environment variables and indexer provider detection (
liquify,nownodes).Middleware usage: Common middleware from
@shapeshiftoss/common-apistandardizes error handling, logging, and metrics collection.Swagger UI integration: API documentation is served under
/docswith a custom title and favicon, supporting developer usability.
Interaction With Other Components
@shapeshiftoss/common-api: Provides foundational middleware, types, and utilities for blockchain API services.@shapeshiftoss/blockbook: Supplies the WebSocket client and blockchain data types for interacting with Blockbook indexers.controller(local): Implements chain-specific logic for transaction/block handling and gas oracle updates.routes(local): Contains REST API route definitions registered dynamically.Registry: Central subscription and event dispatch manager coordinating blockchain events and client subscriptions.Prometheus: Collects and exposes server runtime metrics.
Logger: Standardized structured logging for observability.
Usage Example
Starting the server:
INDEXER_WS_URL=wss://example-indexer.com/ws INDEXER_API_KEY=secretkey PORT=3000 node dist/app.js
Clients can then access:
API docs at
http://localhost:3000/docsHealth check at
http://localhost:3000/healthPrometheus metrics at
http://localhost:3000/metrics
WebSocket clients connect to the same server to subscribe to blockchain events by address.
Visual Diagram
classDiagram
class App {
+express app
+Prometheus prometheus
+Logger logger
+Registry registry
+WebsocketClient blockbook
+Server httpServer
+Server wsServer
+addressFormatter()
+blockHandler(block)
+transactionHandler(tx)
}
class Registry {
+onBlock(block)
+onTransaction(tx)
+addressFormatter
+blockHandler
+transactionHandler
}
class WebsocketClient {
+connect()
+blockHandler[]
+transactionHandler
}
class ConnectionHandler {
+start(connection, registry, blockbook, prometheus, logger)
}
App --> Registry : uses
App --> WebsocketClient : creates
App --> ConnectionHandler : manages WS connections
Registry ..> WebsocketClient : subscribes to events
WebsocketClient --> Registry : calls onBlock/onTransaction
Summary
`app.ts` is the entry point of the Optimism blockchain API server, implementing a REST API and WebSocket server that:
Connects to a blockchain indexer WebSocket feed.
Handles new blocks and transactions with enriched internal data.
Maintains client subscriptions and dispatches relevant events.
Exposes health, metrics, and interactive API documentation.
Leverages a modular, extensible architecture based on common blockchain API components.
This design ensures real-time, scalable access to Optimism blockchain data for client applications while providing robust monitoring and developer-friendly interfaces.