- Module Manager {prereq}
- Messages and Queries {prereq}
The handler
type defined in the Cosmos SDK specifies the typical structure of a handler
function.
Let us break it down:
- The
Msg
is the actual object being processed. - The
Context
contains all the necessary information needed to process themsg
, as well as a cache-wrapped copy of the latest state. If themsg
is succesfully processed, the modified version of the temporary state contained in thectx
will be written to the main state. - The [
Result
] returned tobaseapp
, which contains (among other things) information on the execution of thehandler
,gas
consumption andevents
. +++ https://github.com/cosmos/cosmos-sdk/blob/7d7821b9af132b0f6131640195326aa02b6751db/types/result.go#L15-L40
Module handler
s are typically implemented in a ./handler.go
file inside the module's folder. The module manager is used to add the module's handler
s to the application's router
via the NewHandler()
method. Typically, the manager's NewHandler()
method simply 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 {
switch msg := msg.(type) {
case MsgType1:
return handleMsgType1(ctx, keeper, msg)
case MsgType2:
return handleMsgType2(ctx, keeper, msg)
default:
errMsg := fmt.Sprintf("Unrecognized nameservice Msg type: %v", msg.Type())
return sdk.ErrUnknownRequest(errMsg).Result()
}
}
}
This simple switch returns a handler
function specific to the type of the received message
. These handler
functions are the ones that actually process message
s, and usually follow the following 2 steps:
- First, they perform stateful checks to make sure the
message
is valid. At this stage, themessage
'sValidateBasic()
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 thehandler
can be more expensive and require access to the state. For example, ahandler
for atransfer
message might check that the sending account has enough funds to actually perform the transfer. To access the state, thehandler
needs to call thekeeper
's getter functions. - Then, if the checks are successfull, the
handler
calls thekeeper
'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.
Next is an example of how to return a Result
from the gov
module:
For a deeper look at handler
s, see this example implementation of a handler
function from the nameservice tutorial.
Learn about queriers {hide}