history.go
Overview
The `history.go` file is part of the `cosmos` package and provides functionality to query, manage, and paginate transaction histories from a Cosmos blockchain node via RPC calls. It abstracts the complexity of fetching transactions matching certain queries, handling pagination, filtering based on cursors, and formatting transactions for client consumption.
This file is primarily responsible for:
Defining and managing transaction history state per query source.
Creating query sources for generic account-based and validator-specific transaction searches.
Fetching and merging paginated transaction results from multiple query sources.
Filtering transactions according to client-provided cursors to avoid duplicates.
Encoding and maintaining cursor state to enable efficient paginated responses.
This functionality is critical for applications (such as block explorers or wallets) that need to display a user's transaction history reliably and efficiently.
Types and Functions
Type Aliases
type RequestFn = func(string, int, int) ([]HistoryTx, error)
RequestFn: A function type alias representing an RPC request function.
Parameters:
string: Query string used to filter transactions.int: Page number for paginated results.int: Page size (number of transactions per page).
Returns:
Slice of
HistoryTx(transactions matching the query).errorif the request fails.
Struct: TxState
type TxState struct {
hasMore bool // Indicates if more tx history is available from this source
lastTxID string // Tracks the last transaction ID returned from this source
page int // Current page number for pagination
query string // Query string for the RPC search
request RequestFn // Function to perform the transaction search request
txs []HistoryTx // Cached transactions returned for the current page
}
Holds state for a specific query source (e.g., send transactions, receive transactions).
Manages pagination and caching of transactions.
**Constructor:**
func NewTxState(hasMore bool, query string, request RequestFn) *TxState
Creates a new
TxStateinstance.hasMore: Initially whether there are more transactions to fetch.query: The query string for the transaction search.request: The function used to make the request.
Functions: TxHistorySources and ValidatorTxHistorySources
func TxHistorySources(client APIClient, pubkey string, formatTx func(*coretypes.ResultTx) (*Tx, error)) map[string]*TxState
func ValidatorTxHistorySources(client APIClient, pubkey string, formatTx func(*coretypes.ResultTx) (*Tx, error)) map[string]*TxState
Both functions return a map of query source names to their corresponding
TxState.They define different query filters based on the
pubkey(public key) for either general wallet transactions or validator-specific transactions.Internally define a
requestfunction that performsTxSearchRPC calls via the providedclient.Wrap raw results into
HistoryTxinterface implementations (ResultTx).
**Parameters:**
client APIClient: RPC client interface to perform transaction search.pubkey string: Public key used to construct query filters.formatTx func(*coretypes.ResultTx) (*Tx, error): Callback to format raw RPC transaction results into application-levelTxobjects.
**Returns:**
map[string]*TxState: Mapping from query source names (e.g., "send", "receive", "delegate") to their respectiveTxState.
**Usage Example:**
sources := TxHistorySources(client, "cosmos1abc...", formatTxFunc)
sendTxState := sources["send"]
Struct: History
type History struct {
cursor *Cursor
pageSize int
state map[string]*TxState
}
Manages multiple
TxStatesources to provide a combined, paginated transaction history.Keeps track of pagination state via a
Cursor.Coordinates fetching, filtering, and merging transactions from different query sources.
Method: doRequest
func (h *History) doRequest(txState *TxState) ([]HistoryTx, error)
Executes a paginated request for transactions using the given
TxState.Handles:
Retrying pagination if no transactions remain after filtering.
Filtering transactions based on the current cursor.
Returns a list of filtered transactions or an error.
Method: filterByCursor
func (h *History) filterByCursor(txs []HistoryTx) ([]HistoryTx, error)
Filters out transactions that are already returned according to the current cursor state.
Logic:
Excludes transactions with block height greater than the cursor's block height.
Excludes transactions with the same block height and transaction ID or index less than or equal to the cursor.
Ensures no duplicate transactions are returned.
Returns filtered transactions.
Method: get
func (h *History) get() (*TxHistoryResponse, error)
Main method to retrieve a paginated transaction history response.
Workflow:
Calls
fetch(false)to load initial transaction pages.Merges transactions from all sources, sorting by recency.
Continues fetching more pages if needed to fill
pageSize.Updates cursor state based on last returned transaction.
Encodes the cursor if more transactions are available.
Returns a
TxHistoryResponsecontaining the transactions and optional cursor for next page.
Method: fetch
func (h *History) fetch(more bool) error
Fetches transactions asynchronously for all
TxStatesources.If
moreis true, increments page counters and fetches additional pages.Uses
errgroup.Groupto parallelize requests.Updates each
TxStatewith new transaction data.
Method: hasTxHistory
func (h *History) hasTxHistory() bool
Returns
trueif anyTxStatehas cached transactions available.
Method: getNextTx
func (h *History) getNextTx() (*Tx, error)
Finds the most recent transaction (highest block height) across all sources.
Formats and returns that transaction, removing it from its source cache.
Updates the source's last returned transaction ID.
Helper Function: getMostRecentHeight
func getMostRecentHeight(txs []HistoryTx) int
Returns the block height of the first transaction in the slice.
Returns
-2if no transactions are available (used as sentinel value).
Important Implementation Details and Algorithms
Pagination and Parallel Fetching:
TheHistorystruct manages multiple query sources (TxState) and fetches transactions in parallel to improve performance when dealing with multiple filters (e.g., send, receive, delegate).Cursor-Based Filtering:
To avoid returning duplicate transactions, the system uses aCursorthat tracks the block height, transaction index, and last transaction IDs returned. Transactions are filtered so only new transactions after the cursor are returned.Merging Multiple Sources:
Transactions are merged from different query sources by selecting the most recent transaction among the sources repeatedly until the page size is met.Error Handling:
All RPC calls and formatting functions propagate wrapped errors, preserving call stack information for easier debugging.
Interaction with Other Parts of the System
APIClient Interface:
This file relies on anAPIClientinterface for theTxSearchRPC calls to the blockchain node.Transaction Types:
Uses types such asHistoryTx,ResultTx, andTxto represent transactions at different abstraction levels.Cursor and Pagination:
TheCursortype (likely defined elsewhere) is critical for stateful pagination.Coretypes:
Usesgithub.com/cometbft/cometbft/rpc/core/typespackage for raw transaction results.Error Wrapping:
Usesgithub.com/pkg/errorsfor enhanced error stack traces.
Visual Diagram: Flowchart of Main Functions and Their Relationships
flowchart TD
A[TxHistorySources / ValidatorTxHistorySources] --> B[Create TxState map]
B --> C[NewTxState instances with queries & request function]
D[History struct] --> E[fetch(more)]
E --> F[doRequest(txState)]
F --> G[TxSearch RPC call]
E -->|parallel| F
D --> H[get()]
H --> E
H --> I[filterByCursor(txs)]
H --> J[getNextTx()]
I --> J
J --> K[FormatTx]
H --> L[Update Cursor]
L --> M[Return TxHistoryResponse with Txs and Cursor]
TxHistorySourcesandValidatorTxHistorySourcesproduce query sources asTxStateobjects.Historymanages these sources and fetches/paginates transactions.fetchcallsdoRequestconcurrently to load transactions.getcoordinates fetching, filtering by cursor, merging, and returns the final paginated response.
Summary
The `history.go` file is a core utility within the Cosmos SDK ecosystem for retrieving and managing blockchain transaction histories efficiently. It abstracts the complexities of querying multiple transaction types, handling pagination, filtering duplicates with cursors, and merging multi-source results into a seamless paginated API response. This makes it an essential component for user-facing blockchain clients requiring robust transaction history features.