cosmos-sdk/docs/building-modules/querier.md

3.2 KiB

Queriers

Pre-requisite Readings {hide}

Querier type

The querier type defined in the Cosmos SDK specifies the typical structure of a querier function:

+++ 7d7821b9af/types/queryable.go (L6)

Let us break it down:

  • The path is an array of strings that contains the type of the query, and that can also contain query arguments. See queries for more information.
  • The req itself is primarily used to retrieve arguments if they are too large to fit in the path. This is done using the Data field of req.
  • The Context contains all the necessary information needed to process the query, as well as a cache-wrapped copy of the latest state. It is primarily used by the keeper to access the state.
  • The result res returned to baseapp, marhsalled using the application's codec.

Implementation of a module queriers

Module queriers are typically implemented in a ./internal/keeper/querier.go file inside the module's folder. The module manager is used to add the module's queriers to the application's queryRouter via the NewQuerier() method. Typically, the manager's NewQuerier() method simply calls a NewQuerier() method defined in keeper/querier.go, which looks like the following:

func NewQuerier(keeper Keeper) sdk.Querier {
	return func(ctx sdk.Context, path []string, req abci.RequestQuery) ([]byte, error) {
		switch path[0] {
		case QueryType1:
			return queryType1(ctx, path[1:], req, keeper)

		case QueryType2:
			return queryType2(ctx, path[1:], req, keeper)

		default:
			return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unknown %s query endpoint: %s", types.ModuleName, path[0])
		}
	}
}

This simple switch returns a querier function specific to the type of the received query. At this point of the query lifecycle, the first element of the path (path[0]) contains the type of the query. The following elements are either empty or contain arguments needed to process the query.

The querier functions themselves are pretty straighforward. They generally fetch a value or values from the state using the keeper. Then, they marshall the value(s) using the codec and return the []byte obtained as result.

For a deeper look at queriers, see this example implementation of a querier function from the nameservice tutorial.

Next {hide}

Learn about BeginBlocker and EndBlocker {hide}