handler.go
Overview
[handler.go](/projects/291/69247) defines the `Handler` struct and its methods that extend the generic Cosmos SDK blockchain handler with **Thorchain-specific** functionality for the ShapeShift Unchained platform. It acts as a bridge between the generic Cosmos API framework and Thorchain's unique blockchain characteristics, enabling:
Custom transaction synthesis from Thorchain block-end events.
Affiliate fee revenue tracking and aggregation.
Thorchain-specific transaction history retrieval and message parsing.
WebSocket event handling tailored for Thorchain transactions.
This file is central to processing blockchain data, formatting it for API consumption, and exposing Thorchain-specific endpoints such as affiliate revenue. It relies heavily on Thorchain-specific logic implemented in other packages (`thorchain/`, `cosmos/`) and integrates with an `AffiliateFeeIndexer` for affiliate fee tracking.
Detailed Description of Components
1. Struct: Handler
type Handler struct {
*cosmos.Handler
indexer *AffiliateFeeIndexer
}
**Description:** `Handler` embeds the base `cosmos.Handler` struct to inherit generic Cosmos blockchain handling capabilities and extends it with Thorchain-specific functionality. It adds an `AffiliateFeeIndexer` to maintain and query affiliate fee data.
**Fields:**
Field | Type | Description |
|---|---|---|
`cosmos.Handler` | Embedded struct | Provides base Cosmos blockchain handling logic (e.g., querying blocks, accounts). |
`indexer` | `*AffiliateFeeIndexer` | Tracks affiliate fees and addresses for revenue aggregation. |
2. Method: StartWebsocket
func (h *Handler) StartWebsocket() error
**Description:** Starts the WebSocket client to listen for new block events and process them into Thorchain-specific transactions. Overrides the base Cosmos handler's websocket logic to:
Extract Thorchain transactions by synthesizing them from block-end events.
Format transactions into API-ready structures.
Extract involved addresses for subscription filtering.
**Parameters:** None
**Returns:** `error` — error encountered during WebSocket startup or event handling.
**Implementation Details:**
Registers a block event handler that:
Calls
thorchain.GetTxFromBlockEventsto create synthetic transactions from block-end events.Formats the transaction using
tx.FormatTx().Retrieves addresses involved in the transaction.
Delegates to the embedded base
Handler'sStartWebsocketmethod.
**Example Usage:**
handler := &Handler{...}
err := handler.StartWebsocket()
if err != nil {
log.Fatal(err)
}
3. Struct: Info
type Info struct {
cosmos.Info
}
**Description:** Model struct representing blockchain info, extending the base Cosmos `Info` struct. Used for API responses.
4. Method: GetInfo
func (h *Handler) GetInfo() (api.Info, error)
**Description:** Retrieves blockchain info via the embedded Cosmos handler and wraps it in the Thorchain-specific `Info` type.
**Returns:**
api.Info— blockchain info structure.error— errors during retrieval.
5. Struct: Account
type Account struct {
cosmos.Account
}
**Description:** Model representing account details, extending the base Cosmos `Account` struct.
6. Method: GetAccount
func (h *Handler) GetAccount(pubkey string) (api.Account, error)
**Description:** Fetches account details for a public key or address, delegating to the embedded Cosmos handler and wrapping the result in the Thorchain-specific `Account` type.
**Parameters:**
Name | Type | Description |
|---|---|---|
`pubkey` | string | Public key or address string |
**Returns:**
api.Account— account details.error— error during retrieval.
7. Method: GetTxHistory
func (h *Handler) GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
**Description:** Retrieves transaction history for a given public key or address using Thorchain-specific logic.
**Parameters:**
Name | Type | Description |
|---|---|---|
`pubkey` | string | Public key or address |
`cursor` | string | Pagination cursor (for paging) |
`pageSize` | int | Number of transactions to fetch |
**Returns:**
api.TxHistory— list of transactions.error— in case of failure.
**Implementation Detail:** Delegates to `thorchain.GetTxHistory` to leverage Thorchain-specific event queries and transaction synthesis.
8. Struct: AffiliateRevenue
type AffiliateRevenue struct {
Addresses []string `json:"addresses"`
Amount string `json:"amount"`
}
**Description:** Represents affiliate revenue data for a given time period.
Field | Type | Description |
|---|---|---|
`Addresses` | []string | Affiliate addresses involved |
`Amount` | string | Total amount earned (in RUNE) |
9. Method: GetAffiliateRevenue
func (h *Handler) GetAffiliateRevenue(start int, end int) (*AffiliateRevenue, error)
**Description:** Aggregates affiliate fees recorded by the `AffiliateFeeIndexer` within a start and end timestamp range. Computes the total revenue earned and returns the list of affiliate addresses.
**Parameters:**
Name | Type | Description |
|---|---|---|
`start` | int | Start timestamp (inclusive) |
`end` | int | End timestamp (inclusive) |
**Returns:**
*AffiliateRevenue— aggregated revenue data.error— in case of failure.
**Implementation Details:**
Iterates over
h.indexer.AffiliateFees.Filters fees by timestamp.
Uses
math/big.Intto safely sum large fee amounts.Returns aggregated total and affiliate addresses.
**Usage Example:**
revenue, err := handler.GetAffiliateRevenue(1640995200, 1643673600) // Jan 1 to Feb 1, 2022
if err != nil { ... }
fmt.Println("Affiliate Addresses:", revenue.Addresses)
fmt.Println("Total Revenue (RUNE):", revenue.Amount)
10. Method: ParseMessages
func (h *Handler) ParseMessages(msgs []sdk.Msg, events cosmos.EventsByMsgIndex) []cosmos.Message
**Description:** Parses Cosmos SDK messages and associated events into Thorchain-specific message structures.
**Parameters:**
Name | Type | Description |
|---|---|---|
`msgs` | `[]sdk.Msg` | List of SDK messages to parse |
`events` | `cosmos.EventsByMsgIndex` | Events indexed by message |
**Returns:** `[]cosmos.Message` — parsed messages.
**Details:** Delegates to `thorchain.ParseMessages` to handle Thorchain-specific message types and event parsing.
11. Method: ParseFee
func (h *Handler) ParseFee(tx cosmos.SigningTx, txid string) cosmos.Value
**Description:** Parses the transaction fee for a Thorchain transaction, including adjustments for Thorchain's native fee deduction.
**Parameters:**
Name | Type | Description |
|---|---|---|
`tx` | `cosmos.SigningTx` | The signing transaction |
`txid` | string | Transaction ID |
**Returns:** `cosmos.Value` — parsed fee value including native fee.
**Details:** Calls `thorchain.ParseFee` which adds the native fee amount to the parsed fee to reflect the actual fee paid.
Important Implementation Details and Algorithms
Synthetic Transaction Creation:
StartWebsocketandGetTxHistoryrely onthorchain.GetTxFromBlockEventsandthorchain.GetTxHistorywhich synthesize transactions by analyzing Thorchain-specific block-end events (likeEventOutbound). This captures transactions that may not be directly represented as standard Cosmos SDK transactions.Affiliate Fee Indexing:
TheAffiliateFeeIndexertracks affiliate fee events as they occur. TheGetAffiliateRevenuemethod aggregates these fees using high-precision arithmetic (math/big.Int) for accuracy.Decorator Pattern:
TheHandlerembeds the basecosmos.Handlerand overrides specific methods to insert Thorchain-specific logic, rather than rewriting the entire handler.Big Integer Arithmetic for Fees:
To avoid precision loss in fee calculations, fees are parsed and summed usingbig.Int.WebSocket Event Handling:
The WebSocket client uses a callback that converts raw block events into Thorchain-formatted transactions and extracts involved addresses for subscription management.
Interaction with Other System Components
Embedded
cosmos.Handler:
Provides generic Cosmos blockchain API handling (account queries, base transaction parsing).Thorchain Package (
pkg/thorchain):
Supplies Thorchain-specific transaction parsing, message parsing, and synthetic transaction creation.AffiliateFeeIndexer:
Maintains indexed affiliate fee data used in revenue calculation.CometBFT (
cometbft/types):
Provides blockchain event and block header types.ShapeShift Unchained API (
pkg/api):
Defines generic API interfaces and models extended here for Thorchain.
Visual Diagram
classDiagram
class Handler {
+StartWebsocket() error
+GetInfo() (api.Info, error)
+GetAccount(pubkey string) (api.Account, error)
+GetTxHistory(pubkey string, cursor string, pageSize int) (api.TxHistory, error)
+GetAffiliateRevenue(start int, end int) (*AffiliateRevenue, error)
+ParseMessages(msgs []sdk.Msg, events cosmos.EventsByMsgIndex) []cosmos.Message
+ParseFee(tx cosmos.SigningTx, txid string) cosmos.Value
}
Handler --> cosmos.Handler : embeds
Handler o-- AffiliateFeeIndexer : indexer
class AffiliateFeeIndexer {
+AffiliateFees []AffiliateFee
+AffiliateAddresses []string
}
class cosmos.Handler {
+StartWebsocket() error
+GetInfo() (api.Info, error)
+GetAccount(pubkey string) (api.Account, error)
}
Summary
The [handler.go](/projects/291/69247) file encapsulates the Thorchain-specific extension of the generic Cosmos blockchain handler inside the ShapeShift Unchained platform. It specializes:
WebSocket event handling to produce synthetic Thorchain transactions.
Transaction history queries using Thorchain-centric event parsing.
Affiliate revenue calculation via indexed fee events.
Message and fee parsing customized for Thorchain's blockchain semantics.
By embedding the Cosmos handler and overriding key methods, it cleanly integrates Thorchain-specific logic while reusing generic Cosmos SDK infrastructure, providing a robust, extensible API handler layer tailored for the Thorchain blockchain.