app.ts


Overview

[app.ts](/projects/291/68852) serves as the main entry point for the ShapeShift Bitcoin API server. It sets up an Express.js-based REST API alongside a WebSocket server that interfaces with a blockchain indexer (Blockbook) to provide real-time Bitcoin blockchain data and transaction information. The file orchestrates middleware, routing, WebSocket connection handling, and blockchain event processing, integrating various components such as service controllers, subscription registries, and metrics monitoring.

Key functionalities include:

This file acts as the gateway layer between client applications and underlying Bitcoin blockchain data sources, abstracting blockchain complexities and providing a consistent, developer-friendly API surface.


Detailed Explanations

Imports and Constants


Logger Initialization

const logger = new Logger({
  namespace: ['unchained', 'coinstacks', 'bitcoin', 'api'],
  level: process.env.LOG_LEVEL,
})

Prometheus Metrics

const prometheus = new Prometheus({ coinstack: 'bitcoin' })

Express App Setup

const app = express()

app.use(...middleware.common(prometheus))

app.get('/health', async (_, res) => res.json({ status: 'up', network: 'bitcoin', connections: wsServer.clients.size }))

app.get('/metrics', async (_, res) => {
  res.setHeader('Content-Type', prometheus.register.contentType)
  res.send(await prometheus.register.metrics())
})

Swagger UI Setup

const options = {
  customCss: '.swagger-ui .topbar { display: none }',
  customSiteTitle: 'ShapeShift Bitcoin API Docs',
  customfavIcon: '/public/favi-blue.png',
  swaggerUrl: '/swagger.json',
}

app.use('/public', express.static(join(__dirname, '../../../../../../common/api/public')))
app.use('/swagger.json', express.static(join(__dirname, './swagger.json')))
app.use('/docs', swaggerUi.serve, swaggerUi.setup(undefined, options))

Route Registration and Error Handlers

RegisterRoutes(app)

// Redirect unmatched routes to API docs
app.get('/', async (_, res) => {
  res.redirect('/docs')
})

app.use(middleware.errorHandler, middleware.notFoundHandler)

Blockchain Event Handlers

Block Handler

const blockHandler: BlockHandler<NewBlock, Array<BlockbookTx>> = async (block) => {
  const txs = await service.handleBlock(block.hash)
  return { txs }
}

Transaction Handler

const transactionHandler: TransactionHandler<BlockbookTx, utxo.Tx> = async (blockbookTx) => {
  const tx = service.handleTransaction(blockbookTx)
  const addresses = getAddresses(blockbookTx)
  return { addresses, tx }
}

Registry Setup

const registry = new Registry({ addressFormatter: formatAddress, blockHandler, transactionHandler })

WebSocket Client to Blockchain Indexer

const wsUrl = INDEXER_API_KEY && IS_LIQUIFY ? `${INDEXER_WS_URL}/api=${INDEXER_API_KEY}` : INDEXER_WS_URL
const apiKey = INDEXER_API_KEY && IS_NOWNODES ? INDEXER_API_KEY : undefined

const blockbook = new WebsocketClient(
  wsUrl,
  {
    blockHandler: registry.onBlock.bind(registry),
    transactionHandler: registry.onTransaction.bind(registry),
    apiKey,
  },
  { resetInterval: 15 * 60 * 1000 } // 15 minutes
)

HTTP 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, blockbook, prometheus, logger)
})

Usage Examples

Starting the Server

Set environment variables:

export PORT=3000
export INDEXER_WS_URL=wss://bitcoin-indexer.example.com
export INDEXER_API_KEY=your_api_key_here
export LOG_LEVEL=info

Run the server:

node dist/app.js

Accessing API Docs and Health


Subscribing via WebSocket

Clients connect to the WebSocket server on the same port and subscribe to Bitcoin address updates. On connection:

const ws = new WebSocket('ws://localhost:3000')

ws.onopen = () => {
  ws.send(JSON.stringify({ method: 'subscribe', params: { addresses: ['bitcoinAddress1'] } }))
}

ws.onmessage = (message) => {
  console.log('Received blockchain event:', message.data)
}

Important Implementation Details and Algorithms


Interaction with Other Parts of the System


Diagram: Class and Component Structure

classDiagram
    class App {
        +expressApp: Express
        +wsServer: Server
        +logger: Logger
        +prometheus: Prometheus
        +registry: Registry
        +blockbookClient: WebsocketClient
        +start(): void
    }

    class Registry {
        +addressFormatter: Function
        +blockHandler: Function
        +transactionHandler: Function
        +onBlock(block): void
        +onTransaction(tx): void
    }

    class WebsocketClient {
        +constructor(url: string, handlers: Object, options: Object)
        +connect(): void
        +reset(): void
    }

    class ConnectionHandler {
        +start(connection, registry, blockbook, prometheus, logger): void
    }

    App --> Express
    App --> Logger
    App --> Prometheus
    App --> Registry
    App --> WebsocketClient
    WebsocketClient --> Registry : uses handlers
    wsServer "0..*" --> ConnectionHandler : manages connections

Summary

The [app.ts](/projects/291/68852) file is the core bootstrapper of the ShapeShift Bitcoin API server, combining REST and WebSocket interfaces to deliver rich blockchain data and events. It integrates a modular architecture leveraging controllers, registries, and indexer clients to provide scalable, real-time Bitcoin blockchain services. The file orchestrates middleware, routing, WebSocket connection management, and blockchain event processing with observability and error handling baked in. This design enables client applications to interact with Bitcoin blockchain data efficiently and reliably through a unified API.


End of Documentation for app.ts