controller.ts
Overview
`controller.ts` implements the **Blockbook API Controller**—a TypeScript class that acts as a RESTful HTTP interface to the Blockbook blockchain indexer backend. This controller provides normalized access to blockchain data such as blocks, transactions, addresses, extended public keys (xpubs), unspent transaction outputs (UTXOs), balance histories, and fee estimations.
The main purpose of this file is to abstract and simplify querying blockchain data across multiple supported cryptocurrencies by exposing a consistent, typed API surface with efficient HTTP client logic, error handling, and request retries. It serves as a bridge between client applications and the Blockbook backend indexing service, which maintains cached and indexed blockchain data optimized for fast querying.
Class: Blockbook
Description
`Blockbook` extends [Controller](/projects/291/69211) from the `tsoa` library to define HTTP routes and methods for blockchain data retrieval. It internally uses an Axios HTTP client with retry capabilities to communicate with the Blockbook backend API endpoints.
Properties
Property | Type | Description |
|---|---|---|
`instance` | `AxiosInstance` | Configured Axios HTTP client to send requests to the backend. |
`wsURL` | `string` | WebSocket URL for real-time events, constructed optionally with API key. |
`logger` | `Logger` | Scoped logger instance for tracing and debugging API calls. |
Constructor
constructor(args?: BlockbookArgs, timeout?: number, retries?: number)
Parameters:
args(optional): Configuration parameters including HTTP and WebSocket URLs, API key, and logger instance. Defaults to preset URLs for Ethereum blockbook service.timeout(optional): HTTP request timeout in milliseconds. Defaults to 10,000 ms.retries(optional): Number of HTTP request retries on failures. Defaults to 3.
Behavior:
Initializes the Axios HTTP client with base URL, headers (including API key if provided), timeout, and retry policy.
Configures
axios-retryto automatically retry network errors and idempotent request failures with exponential backoff.Creates a logger child scoped to
blockbook.
Methods
All methods correspond to HTTP GET endpoints under the base route `api/v2`. They make HTTP requests to the Blockbook backend and return typed responses or throw wrapped `ApiError`s on failure.
1. getInfo()
async getInfo(): Promise<Info>
Route:
GET /api/v2Description: Retrieves current status of the Blockbook indexer and connected blockchain backend node.
Returns:
Info— contains chain sync status, best block height, mempool info, versioning, and backend node details.Example Usage:
const info = await blockbook.getInfo()
console.log(info.blockbook.coin, info.backend.chain)
2. getBlockHash(height: number)
async getBlockHash(height: number): Promise<BlockIndex>
Route:
GET /api/v2/block-index/{height}Parameters:
height: Block height (number) to fetch the corresponding block hash.
Description: Returns the hash of the block at the specified height.
Returns:
BlockIndexcontaining the block hash.Example Usage:
const blockIndex = await blockbook.getBlockHash(500000)
console.log(blockIndex.hash)
3. getTransaction(txid: string)
async getTransaction(txid: string): Promise<Tx>
Route:
GET /api/v2/tx/{txid}Parameters:
txid: Transaction ID (string).
Description: Retrieves normalized transaction details across multiple blockchain types.
Returns:
Tx— normalized transaction data including inputs, outputs, block info, coin-specific extensions.Logging: Traces request duration.
Example Usage:
const tx = await blockbook.getTransaction('0x890482efd45fcb660b8eebe42ab4d71a24b97c46c7d9c88b1e4b3cf4bef10110')
console.log(tx.txid, tx.blockHeight)
4. getTransactionSpecific(txid: string)
async getTransactionSpecific(txid: string): Promise<unknown>
Route:
GET /api/v2/tx-specific/{txid}Parameters:
txid: Transaction ID (string).
Description: Returns transaction data exactly as provided by the backend, including all coin-specific fields.
Returns: Raw transaction data (
unknowntype).Logging: Traces request duration.
Example Usage:
const txSpecific = await blockbook.getTransactionSpecific('some-txid')
console.log(txSpecific)
5. getAddress(...)
async getAddress(
address: string,
page?: number,
pageSize?: number,
from?: number,
to?: number,
details?: 'basic' | 'tokens' | 'tokenBalances' | 'txids' | 'txslight' | 'txs',
contract?: string
): Promise<Address>
Route:
GET /api/v2/address/{address}Parameters:
address: Blockchain account address.page(optional): Page number for paginated transaction list (default 1).pageSize(optional): Number of transactions per page (max 1000).from(optional): Filter transactions from this block height.to(optional): Filter transactions up to this block height.details(optional): Level of detail for returned data:basic: balances only, no transactions.tokens: basic + token info.tokenBalances: tokens with balances.txids: tokenBalances + list of transaction IDs.txslight: tokenBalances + limited transaction details.txs(default): tokenBalances + full transaction details.
contract(optional): Filter transactions affecting specific contract address.
Description: Retrieves balances, transactions, tokens, and nonce for an address.
Returns:
Address— includes balances, tokens, transaction list, nonce.Logging: Debug logs request duration and parameters.
Example Usage:
const addressInfo = await blockbook.getAddress('0x37863DF4712e4494dFfc4854862259399354b2BB', 1, 100, undefined, undefined, 'txs')
console.log(addressInfo.balance, addressInfo.tokens)
6. getXpub(...)
async getXpub(
xpub: string,
page?: number,
pageSize?: number,
from?: number,
to?: number,
details?: 'basic' | 'tokens' | 'tokenBalances' | 'txids' | 'txs',
tokens?: 'nonzero' | 'used' | 'derived'
): Promise<Xpub>
Route:
GET /api/v2/xpub/{xpub}Parameters:
xpub: Extended public key string (BIP44/49/84 format).page,pageSize,from,to,details: Same semantics asgetAddress.tokens(optional): Filter tokens (addresses) returned:nonzero(default): addresses with nonzero balance.used: addresses with at least one transaction.derived: all derived addresses.
Description: Returns balances and transactions for an xpub account (Bitcoin-type coins only).
Returns:
Xpub— includes balances, token addresses, transactions, and metadata.Logging: Debug logs request duration and parameters.
Example Usage:
const xpubInfo = await blockbook.getXpub('xpub6DQYbVJSVvJPzpYenir7zVSf2WPZRu69LxZuMezzAKuT6biPcug...')
console.log(xpubInfo.balance, xpubInfo.tokens)
7. getUtxo(account: string, confirmed?: boolean)
async getUtxo(account: string, confirmed?: boolean): Promise<Array<Utxo>>
Route:
GET /api/v2/utxo/{account}Parameters:
account: Address or xpub string.confirmed(optional): Iftrue, returns only confirmed UTXOs; else returns both confirmed and unconfirmed (defaultfalse).
Description: Retrieves the list of unspent transaction outputs (UTXOs) for Bitcoin-like coins. Includes address and derivation path for xpub UTXOs.
Returns: Array of
Utxoobjects sorted by block height descending.Logging: Debug logs request duration.
Example Usage:
const utxos = await blockbook.getUtxo('14mMwtZCGiAtyr8KnnAZYyHmZ9Zvj71h4t', true)
console.log(utxos.length)
8. getBlock(block: string, page?: number)
async getBlock(block: string, page?: number): Promise<Block>
Route:
GET /api/v2/block/{block}Parameters:
block: Block height (number as string) or block hash.page(optional): Page for paginated transactions in block.
Description: Returns block data including transactions, with pagination support.
Returns:
Blockobject with metadata and paginated transaction list.Logging: Traces request duration.
Example Usage:
const blockData = await blockbook.getBlock('500000')
console.log(blockData.hash, blockData.txCount)
9. sendTransaction(hex: string)
async sendTransaction(hex: string): Promise<SendTx>
Route:
GET /api/v2/sendtx/{hex}Parameters:
hex: Serialized raw transaction data (hex string).
Description: Broadcasts a new transaction to the blockchain network via backend.
Returns:
SendTxobject containing the resulting transaction hash.Example Usage:
const result = await blockbook.sendTransaction('0x0100000001...')
console.log(result.result)
10. balanceHistory(account: string, from?: number, to?: number, fiatcurrency?: string, groupBy?: number)
async balanceHistory(
account: string,
from?: number,
to?: number,
fiatcurrency?: string,
groupBy?: number
): Promise<Array<BalanceHistory>>
Route:
GET /api/v2/balancehistory/{account}Parameters:
account: Address or xpub string.from(optional): Start Unix timestamp.to(optional): End Unix timestamp.fiatcurrency(optional): Fiat currency code (e.g., "usd") to include fiat rates.groupBy(optional): Time interval in seconds for grouping results (default 3600).
Description: Retrieves historical balance changes grouped by time intervals with optional fiat conversion rates.
Returns: Array of
BalanceHistoryentries.Example Usage:
const history = await blockbook.balanceHistory('0x37863DF4712e4494dFfc4854862259399354b2BB', 1600000000, 1610000000, 'usd')
console.log(history)
11. estimateFees(blockTimes: number[])
async estimateFees(blockTimes: number[]): Promise<Array<string>>
Route:
GET /api/v2/estimatefeesParameters:
blockTimes: Array of block confirmation targets (in blocks).
Description: Provides estimated network fees (in BTC/kB) for the requested confirmation times.
Returns: Array of fee rate strings corresponding to each requested block time.
Example Usage:
const fees = await blockbook.estimateFees([1, 2, 3])
console.log(fees)
Implementation Details
Axios Client with Retry:
The constructor sets up an Axios client with retry logic viaaxios-retry. Retries occur for network errors, idempotent request errors, HTTP status codes 405-599, and timeout errors (ECONNABORTED). Retry delays use exponential backoff starting at 500ms.API Key Support:
If provided, the API key is included in both the HTTP headers and the WebSocket URL.Error Handling:
API calls catch Axios errors and wrap them into a customApiErrorclass for consistent error responses.Logging:
Uses theLoggerfrom@shapeshiftoss/loggerto trace execution times and debug parameters for each API call.TypeScript Typings:
The file imports strong types from./modelsfor all blockchain data structures ensuring type safety and clarity.Swagger/OpenAPI Integration:
Decorators fromtsoa(@Route,@Tags,@Get,@Path,@Query,@Example) annotate methods to generate API documentation and client SDKs.
Interaction with Other System Components
Blockbook Backend:
This controller is a client of the Blockbook backend blockchain indexer service. It sends REST API requests to fetch indexed blockchain data efficiently.Unified API Layer:
controller.tsforms the Blockbook API subcomponent in the unified API layer, providing normalized blockchain data access to higher-level APIs and client applications.WebSocket Event Subscription Module:
While this file handles on-demand HTTP queries, real-time blockchain events are handled separately by the WebSocket subscription module using thewsURL.Logger Integration:
All API calls are monitored and logged for observability, aiding debugging and performance tracking.
Usage Example
import { Blockbook } from './controller'
const blockbook = new Blockbook({
httpURL: 'https://indexer.ethereum.shapeshift.com',
wsURL: 'wss://indexer.ethereum.shapeshift.com/websocket',
logger: new Logger({ namespace: ['app', 'blockbook'], level: 'debug' }),
})
async function main() {
try {
const info = await blockbook.getInfo()
console.log('Blockbook Info:', info)
const tx = await blockbook.getTransaction('0x890482efd45fcb660b8eebe42ab4d71a24b97c46c7d9c88b1e4b3cf4bef10110')
console.log('Transaction:', tx)
const addressData = await blockbook.getAddress('0x37863DF4712e4494dFfc4854862259399354b2BB', 1, 10, undefined, undefined, 'txs')
console.log('Address:', addressData)
} catch (err) {
console.error('Error querying blockbook:', err)
}
}
main()
Class Diagram
classDiagram
class Blockbook {
+instance: AxiosInstance
+wsURL: string
+logger: Logger
+constructor(args?: BlockbookArgs, timeout?: number, retries?: number)
+getInfo(): Promise~Info~
+getBlockHash(height: number): Promise~BlockIndex~
+getTransaction(txid: string): Promise~Tx~
+getTransactionSpecific(txid: string): Promise~unknown~
+getAddress(address: string, page?: number, pageSize?: number, from?: number, to?: number, details?: string, contract?: string): Promise~Address~
+getXpub(xpub: string, page?: number, pageSize?: number, from?: number, to?: number, details?: string, tokens?: string): Promise~Xpub~
+getUtxo(account: string, confirmed?: boolean): Promise~Array~Utxo~~
+getBlock(block: string, page?: number): Promise~Block~
+sendTransaction(hex: string): Promise~SendTx~
+balanceHistory(account: string, from?: number, to?: number, fiatcurrency?: string, groupBy?: number): Promise~Array~BalanceHistory~~
+estimateFees(blockTimes: number[]): Promise~Array~string~~
}
Summary
`controller.ts` is a core API controller that exposes a rich set of RESTful endpoints to query blockchain data via the Blockbook indexer service. It provides methods to retrieve blocks, transactions, addresses, xpub accounts, UTXOs, balance histories, and estimated fees, all normalized for multiple blockchain types. The file implements robust HTTP client configuration with retries and timeout handling, integrates detailed logging, and uses decorators for automated API documentation generation. It forms a foundational building block in the blockchain data indexing architecture, enabling scalable and consistent blockchain data access for client applications and upper-layer services.