cosmos-sdk/docs/building-modules/handler.md
Marie Gauthier 589835dd98
Update Building Modules documentation (#7473)
* Update module-manager.md

* Update modules #messages doc

* Fix typo

* Update message implementation example link

* Update messages-and-queries.md#queries doc

* Update querier.md

* Update handler.md

* Update links in beginblock-endblock.md

* Update keeper.md

* Update invariants.md

* Update genesis.md

* Update module-interfaces.md#transaction-commands

* Update module-interfaces.md#query-commands

* Update module-interfaces.md#flags

* Update module-interfaces.md#rest

* Update structure.md

* Update module-interfaces.md#grpc

* Update errors.md

* Update module-interfaces.md#grpc-gateway-rest

* Add more info on swagger

* Address comments

* Fix go.sum

* Fix app-anatomy.md

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/querier.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/querier.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Update docs/building-modules/module-interfaces.md

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>

* Address part of review comments

* Update old ref of RegisterQueryService

* Add example code for Manager

* Update queriers.md to query-services.md and refs

* Add new query-services.md

* Revert "Update old ref of RegisterQueryService"

This reverts commit 1ea1ea8559604d5c0aa13951b3016967438da2a5.

* Update keeper.md

* Update handler.md

* Update handler.md

* Update messages-and-queries.md

* Update docs/basics/app-anatomy.md

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>

* Update docs/building-modules/intro.md

Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>

* Fix typo

Co-authored-by: Federico Kunze <31522760+fedekunze@users.noreply.github.com>
Co-authored-by: Amaury Martiny <amaury.martiny@protonmail.com>
2020-10-14 12:38:14 +00:00

5.2 KiB

Handlers

A Handler designates a function that processes messages. Handlers are specific to the module in which they are defined, and only process messages defined within the said module. They are called from baseapp during DeliverTx. {synopsis}

Pre-requisite Readings

handler type

The handler type defined in the Cosmos SDK specifies the typical structure of a handler function.

+++ 7d7821b9af/types/handler.go (L4)

Let us break it down:

  • The Msg is the actual object being processed.
  • The Context contains all the necessary information needed to process the msg, as well as a cache-wrapped copy of the latest state. If the msg is succesfully processed, the modified version of the temporary state contained in the ctx will be written to the main state.
  • The [*Result] returned to baseapp, which contains (among other things) information on the execution of the handler and events. +++ d55c1a2665/proto/cosmos/base/abci/v1beta1/abci.proto (L81-L95)

Implementation of a module handlers

Module handlers are typically implemented in a ./handler.go file inside the module's folder. The module manager is used to add the module's handlers to the application's router via the Route() method. Typically, the manager's Route() method simply constructs a Route that calls a NewHandler() method defined in handler.go, which looks like the following:

func NewHandler(keeper Keeper) sdk.Handler {
	return func(ctx sdk.Context, msg sdk.Msg) (*sdk.Result, error) {
		ctx = ctx.WithEventManager(sdk.NewEventManager())
		switch msg := msg.(type) {
		case *MsgType1:
			return handleMsgType1(ctx, keeper, msg)

		case *MsgType2:
			return handleMsgType2(ctx, keeper, msg)

		default:
			return nil, sdkerrors.Wrapf(sdkerrors.ErrUnknownRequest, "unrecognized %s message type: %T", ModuleName, msg)
		}
	}
}

First, the handler function sets a new EventManager to the context to isolate events per msg. Then, this simple switch returns a handler function specific to the type of the received message. These handler functions are the ones that actually process messages, and usually follow the following 2 steps:

  • First, they perform stateful checks to make sure the message is valid. At this stage, the message's ValidateBasic() method has already been called, meaning stateless checks on the message (like making sure parameters are correctly formatted) have already been performed. Checks performed in the handler can be more expensive and require access to the state. For example, a handler for a transfer message might check that the sending account has enough funds to actually perform the transfer. To access the state, the handler needs to call the keeper's getter functions.
  • Then, if the checks are successfull, the handler calls the keeper's setter functions to actually perform the state transition.

Before returning, handler functions generally emit one or multiple events via the EventManager held in the ctx:

ctx.EventManager().EmitEvent(
		sdk.NewEvent(
			eventType,  // e.g. sdk.EventTypeMessage for a message, types.CustomEventType for a custom event defined in the module
			sdk.NewAttribute(attributeKey, attributeValue),
		),
    )

These events are relayed back to the underlying consensus engine and can be used by service providers to implement services around the application. Click here to learn more about events.

Finally, the handler function returns a *sdk.Result which contains the aforementioned events and an optional Data field.

+++ d55c1a2665/proto/cosmos/base/abci/v1beta1/abci.proto (L81-L95)

Next is an example of how to return a *Result from the gov module:

+++ d55c1a2665/x/gov/handler.go (L67-L70)

For a deeper look at handlers, see this example implementation of a handler function from the gov module.

The handler can then be registered from AppModule.Route() as shown in the example below:

+++ 228728cce2/x/gov/module.go (L143-L146)

Telemetry

New telemetry metrics can be created from the handler when handling messages for instance.

This is an example from the auth module:

+++ d55c1a2665/x/auth/vesting/handler.go (L68-L80)

Next {hide}

Learn about query services {hide}