app.ts
Overview
[app.ts](/projects/291/68852) serves as the main entry point and orchestrator for the Solana blockchain API server built by ShapeShift. It sets up an Express-based HTTP server along with a WebSocket server to provide real-time transaction data streaming and RESTful API endpoints. This file integrates several middleware components, including Prometheus metrics, Swagger API documentation, and custom transaction processing logic tailored for Solana blockchain data.
Key functionalities include:
Exposing health check and metrics endpoints.
Serving API documentation through Swagger UI.
Handling Solana transaction logs via WebSocket and processing them into usable transaction entities.
Managing WebSocket client connections for live data ingestion from an external Solana data source.
Registering REST API routes for Solana blockchain interactions.
This file ties together various modules such as transaction models, route definitions, utilities, and WebSocket clients to provide a cohesive API service.
Detailed Breakdown
Constants and Environment Variables
PORT(number|string): The HTTP server port, defaulting to3000if not specified in environment variables.WS_URL(string | undefined): WebSocket endpoint URL for real-time Solana data; mandatory env var.WS_API_KEY(string | undefined): API key for authenticating the WebSocket client; mandatory env var.
Throws an error if either `WS_URL` or `WS_API_KEY` is not set, preventing the app from starting without essential configuration.
Logger
export const logger = new Logger({
namespace: ['unchained', 'coinstacks', 'solana', 'api'],
level: process.env.LOG_LEVEL,
})
Purpose: Provides structured and namespaced logging throughout the application.
Uses
@shapeshiftoss/loggerwith namespaces specific to this Solana API.Log level configurable via environment variables.
Prometheus Metrics
const prometheus = new Prometheus({ coinstack: 'solana' })
Instantiates Prometheus client to collect metrics with the label
"coinstack": "solana".Metrics are exposed under
/metricsendpoint with appropriate content type.
Express Application Setup
const app = express()
app.use(...middleware.common(prometheus))
Creates an Express app.
Attaches common middleware (likely for logging, CORS, JSON parsing, etc.) integrated with Prometheus metrics.
HTTP Endpoints
GET /health
Returns a JSON object indicating service health status and asset type.{ "status": "up", "asset": "solana" }GET /metrics
Exposes Prometheus metrics in the required format.Static Assets and API Docs
/public: Serves static files (e.g., favicon)./swagger.json: Serves OpenAPI specification file./docs: Swagger UI interface for API documentation.
Root Redirect (
/)
Redirects to/docsfor user-friendly access to API docs.Error Handling Middleware
Registers handlers to catch 404 and other errors gracefully.
Swagger UI Options
const options: swaggerUi.SwaggerUiOptions = {
customCss: '.swagger-ui .topbar { display: none }',
customSiteTitle: 'ShapeShift Solana API Docs',
customfavIcon: '/public/favi-blue.png',
swaggerUrl: '/swagger.json',
}
Customizes the Swagger UI appearance and metadata.
Hides the top bar for a cleaner look.
Uses project branding for title and favicon.
Route Registration
RegisterRoutes(app)
Imports routing logic from
./routesmodule.Registers REST API endpoints related to Solana blockchain operations.
This helps modularize route definitions outside this main file.
Transaction Handler
const transactionHandler: TransactionHandler<Logs, Tx> = async (log) => {
const tx = await getTransaction(log.signature, true)
const addresses = tx.accountData.map((key) => key.account)
return { addresses, tx }
}
Processes Solana transaction logs (
Logs) and extracts a domain-specific transaction object (Tx).Uses
getTransactionutility to fetch detailed transaction data by signature.Extracts associated addresses from the transaction’s account data.
**Parameters:**
Name | Type | Description |
|---|---|---|
`log` | `Logs` | Solana blockchain transaction log containing signature and metadata |
**Returns:**
Type | Description |
|---|---|
`Promise<{ addresses: string[], tx: Tx }>` | Returns an object containing the involved addresses and the transaction data |
**Usage Example:**
const log: Logs = ...; // obtained from Solana WebSocket feed
const result = await transactionHandler(log);
console.log(result.addresses, result.tx);
Registry Initialization
const registry = new Registry({
addressFormatter: (address: string) => address,
transactionHandler,
})
Registrymanages active blockchain addresses and transaction processing.The
addressFormatteris identity here (no changes to address strings).Passes the custom
transactionHandlerto process incoming transactions.Acts as a mediator between incoming data and WebSocket client connections.
WebSocket Client Setup
const helius = new WebsocketClient(WS_URL, {
apiKey: WS_API_KEY,
transactionHandler: registry.onTransaction.bind(registry),
})
Instantiates a WebSocket client (
WebsocketClient) to connect to the external Solana data source.Authenticates using provided
WS_API_KEY.Binds the registry’s
onTransactionmethod as the transaction handler callback for incoming messages.Enables real-time transaction data ingestion.
Server and WebSocket Server Initialization
const server = app.listen(PORT, () => logger.info('Server started'))
const wsServer = new Server({ server })
wsServer.on('connection', (connection) => {
ConnectionHandler.start(connection, registry, helius, prometheus, logger)
})
Starts the Express HTTP server on the configured port.
Creates a WebSocket server (
wsServer) that shares the same HTTP server.On each client WebSocket connection, delegates handling to
ConnectionHandler.start:This manages client subscriptions, message dispatching, and integrates with the registry, WebSocket client, Prometheus metrics, and logger.
Implementation Details and Algorithms
Transaction Handling:
Transactions are processed asynchronously by fetching detailed transaction data viagetTransactionby signature. The handler extracts involved account addresses, enabling filtering or routing on those addresses.Registry Pattern:
TheRegistryabstracts management of active addresses and transaction processing logic. It serves as a centralized event handler for incoming blockchain data, ensuring modular and extensible transaction processing.WebSocket Client:
Uses an externally provided WebSocket URL and API key to connect to a Solana data source, receiving transaction logs in real time that trigger the registry's processing pipeline.Middleware Chaining:
Uses common middleware from@shapeshiftoss/common-apito apply best practices such as logging, metrics collection, error handling, and 404 responses.API Documentation:
Swagger UI and JSON spec are served statically, allowing easy API exploration and client generation.
Interactions with Other Modules
@shapeshiftoss/common-api: Provides middleware, Prometheus metrics integration, and connection/transaction handler abstractions.@shapeshiftoss/logger: Structured logging utility../models: Defines theTxtransaction model representing Solana transactions../routes: Contains REST API route definitions registered onto the Express app../utils: Contains helper functions includinggetTransactionto fetch transaction details../websocket: WebSocket client implementation connecting to Solana data feed.ws: WebSocket server for handling client connections to this API server.
Usage Example
Start server:
Ensure environment variablesWS_URLandWS_API_KEYare set, then run:node dist/app.jsAccess health check:
curl http://localhost:3000/healthAccess API docs:
Open browser athttp://localhost:3000/docsConnect via WebSocket:
Use the WebSocket URL exposed by this server (e.g.,ws://localhost:3000) to receive real-time transaction updates.
Mermaid Class Diagram
classDiagram
class app {
+PORT: number|string
+WS_URL: string
+WS_API_KEY: string
+logger: Logger
+prometheus: Prometheus
+app: express.Application
+transactionHandler(log: Logs): Promise<{addresses: string[], tx: Tx}>
+registry: Registry
+helius: WebsocketClient
+server: http.Server
+wsServer: WebSocket.Server
}
class Logger {
+namespace: string[]
+level: string
+info(msg: string)
+error(msg: string)
}
class Prometheus {
+coinstack: string
+register: any
+metrics(): Promise<string>
}
class Registry {
+addressFormatter(address: string): string
+transactionHandler: Function
+onTransaction(tx: any): void
}
class WebsocketClient {
+constructor(url: string, options: object)
+apiKey: string
+transactionHandler: Function
+connect(): void
}
class ConnectionHandler {
+start(conn: WebSocket, registry: Registry, client: WebsocketClient, prometheus: Prometheus, logger: Logger): void
}
app --> Logger
app --> Prometheus
app --> express.Application : app
app --> Registry
app --> WebsocketClient
app --> ConnectionHandler
Summary
The [app.ts](/projects/291/68852) file is the central bootstrapper of the ShapeShift Solana API service. It configures HTTP and WebSocket servers, integrates middleware for observability and error handling, registers REST endpoints and Swagger documentation, and orchestrates the processing of real-time Solana blockchain transactions via WebSocket streams. The modular design leverages abstractions like `Registry` and `ConnectionHandler` to decouple concerns and improve maintainability. This file is critical for initializing and running the Solana API server within the overall ShapeShift infrastructure.