handler.go
Overview
The [handler.go](/projects/291/69233) file defines the core request handling mechanism for interacting with the Cosmos blockchain network within the application. It provides the primary interface and implementation for processing both WebSocket and REST API requests related to blockchain data such as accounts, transactions, staking, and fees.
The file defines the `RouteHandler` interface which outlines the essential methods for WebSocket lifecycle management and REST endpoints. The main concrete implementation is the `Handler` struct, which integrates coin-specific logic alongside common Cosmos SDK interactions.
This handler encapsulates complex blockchain operations such as transaction decoding, event parsing, fee calculation, and staking queries, providing a clean and reusable abstraction layer between the application and the underlying Cosmos SDK and Tendermint RPC clients.
Classes and Interfaces
RouteHandler Interface
Defines the contract for handling blockchain-related requests:
Method | Description |
|---|---|
`StartWebsocket() error` | Starts the WebSocket client to listen for new blockchain events and transactions. |
`StopWebsocket()` | Stops the WebSocket client and closes connections. |
`NewWebsocketConnection(conn *ws.Conn, manager *websocket.Manager)` | Registers and starts a new WebSocket connection. |
`GetInfo() (api.Info, error)` | Retrieves basic blockchain info (e.g., network name). |
`GetAccount(pubkey string) (api.Account, error)` | Fetches account details by public key/address. |
`GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)` | Retrieves transaction history for an account. |
`GetTx(txid string) (api.Tx, error)` | Retrieves a specific transaction by its ID. |
`SendTx(hex string) (string, error)` | Broadcasts a raw transaction hex to the network. |
`EstimateGas(rawTx string) (string, error)` | Estimates gas usage of a raw transaction. |
CoinSpecificHandler Interface
Defines coin-specific parsing methods that must be implemented by handlers tailored to particular Cosmos-based chains:
Method | Description |
|---|---|
`ParseMessages([]sdk.Msg, EventsByMsgIndex) []Message` | Parses blockchain messages from a transaction with event data. |
`ParseFee(tx SigningTx, txid string) Value` | Parses and calculates the transaction fee. |
Handler Struct
The primary implementation of `RouteHandler`, combining generic Cosmos SDK logic with coin-specific behavior.
Field | Type | Description |
|---|---|---|
`ParseMessages` | `func([]sdk.Msg, EventsByMsgIndex) []Message` | Coin-specific function for parsing messages. |
`ParseFee` | `func(tx SigningTx, txid string) Value` | Coin-specific function for parsing fees. |
`HTTPClient` | `APIClient` | Client for making HTTP API calls to the Cosmos node. |
`WSClient` | `*WSClient` | WebSocket client for real-time blockchain event subscriptions. |
`BlockService` | `*BlockService` | Service to fetch block data by height. |
`Denom` | `string` | The denomination (token symbol) used in the blockchain. |
`NativeFee` | `int` | Native fee unit value for transactions. |
Functions and Methods
ValidateCoinSpecific(handler interface{}) error
Purpose:
Validates at runtime that a givenhandlerimplements theCoinSpecificHandlerinterface and assigns its methods to theHandlerstruct's corresponding function fields.Parameters:
handler— an object expected to implementCoinSpecificHandler.
Returns:
error— non-nil if validation or assignment fails.
Usage Example:
var h Handler var coinHandler CoinSpecificHandler = &MyCoinHandler{} err := h.ValidateCoinSpecific(coinHandler) if err != nil { log.Fatalf("Invalid coin handler: %v", err) }Details:
Uses reflection to check for required methods, returning descriptive errors if any methods are missing.
NewWebsocketConnection(conn *ws.Conn, manager *websocket.Manager)
Purpose:
Creates a new WebSocket connection wrapper and starts it.Parameters:
conn— underlying raw WebSocket connection.manager— WebSocket connection manager handling multiple connections.
Returns:
voidDetails:
Wraps the raw connection in a higher-levelwebsocket.Connectionstruct coupled with the handler's WS client, then starts the connection.
StartWebsocket() error
Purpose:
Starts the WebSocket client to listen for new transactions and handle them in real-time.Returns:
error— if the WebSocket client fails to start.
Details:
Registers a transaction handler callback that decodes each incoming transaction, parses events, constructs aTxobject with detailed metadata, and extracts involved addresses for subscription tracking.
StopWebsocket()
Purpose:
Stops the WebSocket client and closes all active connections.Returns:
void
GetInfo() (api.Info, error)
Purpose:
Returns basic blockchain network information.Returns:
api.Info— contains network identification and metadata.error— if fetching info fails (currently always nil).
Details:
Returns a fixed network string"mainnet". Can be extended for dynamic network detection.
GetAccount(pubkey string) (api.Account, error)
Purpose:
Fetches account details including balances, sequence numbers, and assets by public key.Parameters:
pubkey— account public key or address string.
Returns:
api.Account— populated account object.error— on failure to retrieve any data.
Details:
Useserrgroupto concurrently fetch account metadata and balances via HTTP API client, then consolidates into a singleAccountstruct.
GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
Purpose:
Retrieves paginated transaction history for a given account.Parameters:
pubkey— target account public key.cursor— pagination cursor string for next page retrieval.pageSize— number of transactions per page.
Returns:
api.TxHistory— transaction history with pagination info.error— on failure.
Details:
Constructs appropriate sources for fetching transaction history, calls HTTP client, and formats results.
GetValidatorTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
Purpose:
Similar toGetTxHistorybut specifically fetches validator-related transactions.Parameters & Returns: Same as
GetTxHistory.
GetTx(txid string) (api.Tx, error)
Purpose:
Retrieves and formats a single transaction by its ID.Parameters:
txid— transaction hash string.
Returns:
api.Tx— formatted transaction object.error— if retrieval or formatting fails.
Details:
Fetches raw transaction data then formats it viaFormatTxto include block and event details.
SendTx(hex string) (string, error)
Purpose:
Broadcasts a raw transaction encoded in hex format to the network.Parameters:
hex— raw transaction hex string.
Returns:
Transaction hash (string) or error on failure.
EstimateGas(rawTx string) (string, error)
Purpose:
Returns the estimated gas required to execute a raw transaction.Parameters:
rawTx— raw transaction string.
Returns:
Gas estimate as a string, or error.
GetStaking(pubkey string, apr *big.Float) (*Staking, error)
Purpose:
Retrieves staking-related data including delegations, redelegations, unbondings, and rewards for an account.Parameters:
pubkey— account public key.apr— current annual percentage rate for rewards calculations.
Returns:
*Staking— comprehensive staking data structure.error— if any network call fails.
Details:
Uses concurrent goroutines to fetch each staking component independently and consolidates results.
FormatTx(tx *coretypes.ResultTx) (*Tx, error)
Purpose:
Converts a raw blockchain transaction result into a richTxstruct with block data, events, fees, and messages.Parameters:
tx— raw transaction result from Tendermint RPC.
Returns:
*Tx— fully formatted transaction.error— if decoding or block lookup fails.
Details:
Steps:Fetch block info for the transaction height.
Decode transaction bytes into Cosmos SDK message and signing transaction.
Parse events from transaction results.
Calculate fee and parse messages using coin-specific functions.
Compute confirmations based on latest block height.
Important Implementation Details and Algorithms
Dynamic Coin-Specific Behavior:
TheHandlerstruct uses function fields (ParseMessages,ParseFee) assigned at runtime viaValidateCoinSpecificto inject coin-specific parsing logic without requiring multiple inheritance or large interface implementations. This design enables flexible extension to multiple Cosmos-based chains.Concurrency for Data Fetching:
Methods likeGetAccountandGetStakingusegolang.org/x/sync/errgroupto parallelize multiple HTTP API calls, improving latency and responsiveness.WebSocket Transaction Handling:
WebSocket client listens for new transactions (types.EventDataTx), decodes them, parses events, and constructs rich transaction objects that include memo, fees, gas used/wanted, and involved addresses for subscription filtering.Transaction ID Generation:
Transaction IDs for WebSocket events are computed by SHA-256 hashing of the raw transaction bytes and formatting as a hex string, ensuring consistent identification.Error Wrapping:
Usesgithub.com/pkg/errorsto wrap errors with contextual messages, aiding debugging and error tracing.
Interaction with Other System Components
API Client (
APIClient):
The handler relies heavily on anHTTPClientinterface to fetch blockchain data via HTTP REST endpoints, including accounts, balances, transactions, blocks, staking, and gas estimations.WebSocket Client (
*WSClient):
The handler's WebSocket client manages live updates of new transactions and events, enabling real-time streaming features.Block Service (
*BlockService):
Used to retrieve block data by height to enrich transaction information with block hash, timestamp, and height.WebSocket Connection Manager (
websocket.Manager):
Manages multiple active WebSocket connections and routes messages appropriately.Cosmos SDK Types and Tendermint RPC:
Utilizes Cosmos SDK message types (sdk.Msg) and Tendermint's RPC types (coretypes.ResultTx) to decode and interpret blockchain data.
Visual Diagram
classDiagram
class RouteHandler {
+StartWebsocket() error
+StopWebsocket()
+NewWebsocketConnection(conn *ws.Conn, manager *websocket.Manager)
+GetInfo() (api.Info, error)
+GetAccount(pubkey string) (api.Account, error)
+GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
+GetTx(txid string) (api.Tx, error)
+SendTx(hex string) (string, error)
+EstimateGas(rawTx string) (string, error)
}
class CoinSpecificHandler {
+ParseMessages([]sdk.Msg, EventsByMsgIndex) []Message
+ParseFee(tx SigningTx, txid string) Value
}
class Handler {
+ParseMessages func([]sdk.Msg, EventsByMsgIndex) []Message
+ParseFee func(tx SigningTx, txid string) Value
+HTTPClient APIClient
+WSClient *WSClient
+BlockService *BlockService
+Denom string
+NativeFee int
+ValidateCoinSpecific(handler interface{}) error
+NewWebsocketConnection(conn *ws.Conn, manager *websocket.Manager)
+StartWebsocket() error
+StopWebsocket()
+GetInfo() (api.Info, error)
+GetAccount(pubkey string) (api.Account, error)
+GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
+GetValidatorTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
+GetTx(txid string) (api.Tx, error)
+SendTx(hex string) (string, error)
+EstimateGas(rawTx string) (string, error)
+GetStaking(pubkey string, apr *big.Float) (*Staking, error)
+FormatTx(tx *coretypes.ResultTx) (*Tx, error)
}
RouteHandler <|.. Handler
CoinSpecificHandler <|.. Handler
Summary
The [handler.go](/projects/291/69233) file provides a robust, extensible framework for interacting with the Cosmos blockchain in both real-time and RESTful manners. It cleanly separates coin-specific logic from general blockchain operations, leverages concurrent calls for efficient data retrieval, and integrates tightly with WebSocket and HTTP clients to offer a comprehensive blockchain API surface.
This modular design supports easy adaptation to different Cosmos SDK-based blockchains by injecting coin-specific parsing logic while maintaining a unified handler interface for the application.