app.ts
Overview
`app.ts` is the main entry point for the Bitcoin Cash API server within the ShapeShift Unchained coinstacks project. It sets up an Express.js HTTP server combined with a WebSocket server to provide real-time blockchain data and RESTful API endpoints. The file's primary responsibilities include:
Initializing an Express app with middleware, health checks, metrics, and API documentation endpoints.
Registering REST API routes.
Setting up WebSocket connections to a Bitcoin Cash blockchain indexer (via
@shapeshiftoss/blockbook).Handling incoming blockchain blocks and transactions using a registry pattern.
Exposing Prometheus metrics for observability.
Logging and error handling.
This file bridges the underlying blockchain data sources (via WebSocket client) with API consumers, ensuring efficient, real-time updates and a rich API surface.
Detailed Explanation
Imports and Constants
External libraries:
express: HTTP server framework.ws: WebSocket server.swagger-ui-express: API documentation UI.Various
@shapeshiftossscoped packages for blockchain data, logging, metrics, and API utilities.
Environment variables:
PORT: HTTP server port (default 3000).INDEXER_WS_URL: WebSocket URL for the Bitcoin Cash indexer (required).INDEXER_API_KEY: API key for authenticating with the indexer service.
Throws an error immediately if
INDEXER_WS_URLis not set to prevent startup without backend connectivity.
Express Application Setup
const app = express()
app.use(...middleware.common(prometheus))
Sets up Express application.
Attaches common middleware from
@shapeshiftoss/common-api, including instrumentation middleware backed by Prometheus metrics.
HTTP Routes
Health check endpoint:
GET /health
Returns JSON with server status, network name, and current WebSocket connections count.Metrics endpoint:
GET /metrics
Returns Prometheus metrics in the appropriate content type.Static file serving:
Serves static files under
/publicfrom the shared API public directory.Serves the Swagger JSON spec at
/swagger.json.Serves Swagger UI at
/docswith customized UI options (title, favicon, CSS).
Route registration:
RegisterRoutes(app)imports and registers all REST API routes.Root redirect:
Redirects/to/docsto guide users to API documentation.Error handling:
Uses generic error and 404 handlers from middleware.
Blockchain Handlers
Two asynchronous handler functions process blockchain data received via WebSocket:
blockHandler
const blockHandler: BlockHandler<NewBlock, Array<BlockbookTx>> = async (block) => {
const txs = await service.handleBlock(block.hash)
return { txs }
}
Parameters:
block: aNewBlockobject representing a newly confirmed blockchain block.
Functionality:
Calls
service.handleBlockwith the block's hash to process and retrieve transactions.
Returns:
An object containing the array of transactions in the block.
transactionHandler
const transactionHandler: TransactionHandler<BlockbookTx, utxo.Tx> = async (blockbookTx) => {
const tx = service.handleTransaction(blockbookTx)
const addresses = getAddresses(blockbookTx)
return { addresses, tx }
}
Parameters:
blockbookTx: a transaction from Blockbook representing a blockchain transaction.
Functionality:
Processes the transaction via
service.handleTransaction.Extracts involved addresses using
getAddresses.
Returns:
An object containing the affected addresses and the processed transaction.
Registry Setup
const registry = new Registry({ addressFormatter: formatAddress, blockHandler, transactionHandler })
Instantiates a
Registryobject from@shapeshiftoss/common-api:Responsible for coordinating blockchain data processing.
Uses the provided formatting function, block handler, and transaction handler.
The registry provides methods
onBlockandonTransactionwhich are bound and passed to the WebSocket client.
WebSocket Client Setup
const blockbook = new WebsocketClient(
INDEXER_WS_URL,
{
apiKey: INDEXER_API_KEY,
blockHandler: registry.onBlock.bind(registry),
transactionHandler: registry.onTransaction.bind(registry),
},
{ resetInterval: 15 * 60 * 1000 } // 15 minutes
)
Connects to the Bitcoin Cash indexer WebSocket endpoint.
Authenticates with
apiKey.Registers handlers for incoming blocks and transactions via the registry.
Configured to reset connection every 15 minutes to ensure stability.
Server and WebSocket Server Initialization
const server = app.listen(PORT, () => logger.info('Server started'))
const wsServer = new Server({ server })
Starts HTTP server on defined port.
Creates a WebSocket server attached to the HTTP server to allow upgrades on the same port.
WebSocket Connection Handling
wsServer.on('connection', (connection) => {
ConnectionHandler.start(connection, registry, blockbook, prometheus, logger)
})
On each incoming WebSocket client connection:
Delegates connection management to
ConnectionHandler.start.Passes the registry, WebSocket client, Prometheus metrics, and logger for lifecycle and message handling.
The `ConnectionHandler` likely manages subscriptions, message routing, and client lifecycle events.
Usage Examples
Starting the Server
Assuming environment variables are set:
export INDEXER_WS_URL=wss://indexer.example.com/ws
export INDEXER_API_KEY=your_api_key
export PORT=3000
node dist/app.js
Accessing API
Health check:
GET http://localhost:3000/healthPrometheus metrics:
GET http://localhost:3000/metricsAPI docs:
http://localhost:3000/docs
WebSocket Client
Clients can connect to the same port via WebSocket to receive real-time blockchain updates (subscription and messaging details handled by `ConnectionHandler`).
Implementation Details and Algorithms
Registry Pattern: The use of a
Registrycentralizes management of blockchain events and transaction processing, simplifying handler binding and stateful coordination.WebSocket Resilience: The WebSocket client auto-resets every 15 minutes to mitigate stale connections or memory leaks.
Middleware Composition: Common middleware from
@shapeshiftoss/common-apiensures consistent metrics, error handling, and request processing across all routes.Swagger Integration: Embeds OpenAPI documentation served dynamically with custom branding, improving developer experience.
Logging: Uses a structured logger with namespaces for filtering logs related to this API stack.
Interaction with Other System Parts
@shapeshiftoss/blockbook: Provides blockchain data via WebSocket client.@shapeshiftoss/common-api: Supplies middleware, metrics, handlers, and utilities../controller: Contains business logic for processing blocks and transactions (service.handleBlock,service.handleTransaction)../routes: Defines REST API endpoints registered on the Express app.Prometheus: Collects and exposes blockchain and API metrics for monitoring.
Client Applications: Connect via REST or WebSocket to consume blockchain data and respond accordingly.
Class and Function Summary
Name | Type | Description |
|---|---|---|
`blockHandler` | Function | Async handler to process new blockchain blocks and return transactions. |
`transactionHandler` | Function | Async handler to process individual blockchain transactions and extract addresses. |
`registry` | Class | Manages blockchain event processing, wrapping handlers for blocks and transactions. |
`blockbook` | Class | WebSocket client connecting to the blockchain indexer, providing real-time block/tx data. |
`app` | Object | Express application instance configuring middleware and HTTP routes. |
`server` | Object | HTTP server instance listening for incoming HTTP and WS connections. |
`wsServer` | Class | WebSocket server handling client connections for real-time communication. |
Visual Diagram
classDiagram
class App {
+use()
+get()
+listen()
}
class BlockHandler {
<<function>>
+handleBlock(block: NewBlock) : Promise<{txs: BlockbookTx[]}>
}
class TransactionHandler {
<<function>>
+handleTransaction(tx: BlockbookTx) : utxo.Tx
}
class Registry {
-addressFormatter: function
-blockHandler: BlockHandler
-transactionHandler: TransactionHandler
+onBlock()
+onTransaction()
}
class WebsocketClient {
-url: string
-apiKey: string
-blockHandler: function
-transactionHandler: function
+connect()
}
class Server {
+on(event: string, listener: function)
}
class ConnectionHandler {
+start(connection, registry, blockbook, prometheus, logger)
}
App --> Server : listens
Server --> WebsocketClient : manages connection
Server --> ConnectionHandler : manages WS client connections
WebsocketClient --> Registry : calls onBlock, onTransaction
Registry --> BlockHandler : processes blocks
Registry --> TransactionHandler : processes transactions
Summary
`app.ts` is a foundational file setting up the Bitcoin Cash API server combining HTTP REST endpoints with real-time WebSocket streaming. It orchestrates blockchain data ingestion, processing, and client communication, while providing monitoring and documentation endpoints. The modular design leverages ShapeShift's common API utilities to maintain clean separation of concerns and extensibility. This file acts as the central hub connecting blockchain data providers, business logic, and API consumers in a performant, maintainable manner.