Events
Event
s are objects that contain information about the execution of the application. They are mainly used by service providers like block explorers and wallet to track the execution of various messages and index transactions.
Pre-requisite Readings
Events
Events are implemented in the Cosmos SDK as an alias of the ABCI Event
type and
take the form of: {eventType}.{attributeKey}={attributeValue}
.
https://github.com/cometbft/cometbft/blob/v0.37.0/proto/tendermint/abci/types.proto#L334-L343
An Event contains:
- A
type
to categorize the Event at a high-level; for example, the Cosmos SDK uses the"message"
type to filter Events byMsg
s. - A list of
attributes
are key-value pairs that give more information about the categorized Event. For example, for the"message"
type, we can filter Events by key-value pairs usingmessage.action={some_action}
,message.module={some_module}
ormessage.sender={some_sender}
. - A
msg_index
to identify which messages relate to the same transaction
To parse the attribute values as strings, make sure to add '
(single quotes) around each attribute value.
Typed Events are Protobuf-defined messages used by the Cosmos SDK
for emitting and querying Events. They are defined in a event.proto
file, on a per-module basis and are read as proto.Message
.
Legacy Events are defined on a per-module basis in the module's /types/events.go
file.
They are triggered from the module's Protobuf Msg
service
by using the EventManager
.
In addition, each module documents its events under in the Events
sections of its specs (x/{moduleName}/README.md
).
Lastly, Events are returned to the underlying consensus engine in the response of the following ABCI messages:
Examples
The following examples show how to query Events using the Cosmos SDK.
Event | Description |
---|---|
tx.height=23 | Query all transactions at height 23 |
message.action='/cosmos.bank.v1beta1.Msg/Send' | Query all transactions containing a x/bank Send Service Msg . Note the ' s around the value. |
message.module='bank' | Query all transactions containing messages from the x/bank module. Note the ' s around the value. |
create_validator.validator='cosmosval1...' | x/staking-specific Event, see x/staking SPEC. |
EventManager
In Cosmos SDK applications, Events are managed by an abstraction called the EventManager
.
Internally, the EventManager
tracks a list of Events for the entire execution flow of a
transaction or BeginBlock
/EndBlock
.
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/events.go#L24-L27
The EventManager
comes with a set of useful methods to manage Events. The method
that is used most by module and application developers is EmitTypedEvent
or EmitEvent
that tracks
an Event in the EventManager
.
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/types/events.go#L53-L62
Module developers should handle Event emission via the EventManager#EmitTypedEvent
or EventManager#EmitEvent
in each message
Handler
and in each BeginBlock
/EndBlock
handler. The EventManager
is accessed via
the Context
, where Event should be already registered, and emitted like this:
Typed events:
https://github.com/cosmos/cosmos-sdk/blob/v0.47.0-rc1/x/group/keeper/msg_server.go#L88-L91
Legacy events:
ctx.EventManager().EmitEvent(
sdk.NewEvent(eventType, sdk.NewAttribute(attributeKey, attributeValue)),
)
Module's handler
function should also set a new EventManager
to the context
to isolate emitted Events per message
:
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) {
See the Msg
services concept doc for a more detailed
view on how to typically implement Events and use the EventManager
in modules.
Subscribing to Events
You can use CometBFT's Websocket to subscribe to Events by calling the subscribe
RPC method:
{
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "tm.event='eventCategory' AND eventType.eventAttribute='attributeValue'"
}
}
The main eventCategory
you can subscribe to are:
NewBlock
: Contains Events triggered duringBeginBlock
andEndBlock
.Tx
: Contains Events triggered duringDeliverTx
(i.e. transaction processing).ValidatorSetUpdates
: Contains validator set updates for the block.
These Events are triggered from the state
package after a block is committed. You can get the
full list of Event categories on the CometBFT Go documentation.
The type
and attribute
value of the query
allow you to filter the specific Event you are looking for. For example, a Mint
transaction triggers an Event of type EventMint
and has an Id
and an Owner
as attributes
(as defined in the events.proto
file of the NFT
module).
Subscribing to this Event would be done like so:
{
"jsonrpc": "2.0",
"method": "subscribe",
"id": "0",
"params": {
"query": "tm.event='Tx' AND mint.owner='ownerAddress'"
}
}
where ownerAddress
is an address following the AccAddress
format.
The same way can be used to subscribe to legacy events.
Default Events
There are a few events that are automatically emitted for all messages, directly from baseapp
.
message.action
: The name of the message type.message.sender
: The address of the message signer.message.module
: The name of the module that emitted the message.
The module name is assumed by baseapp
to be the second element of the message route: "cosmos.bank.v1beta1.MsgSend" -> "bank"
.
In case a module does not follow the standard message path, (e.g. IBC), it is advised to keep emitting the module name event.
Baseapp
only emits that event if the module have not already done so.