Events
Event subscription APIs
Fetch events posted by the consensus node.
/eventsFetch a batch of events posted by the consensus node and matching a specified query string.
The query grammar is defined in pubsub/query/syntax. An empty query matches all events; otherwise a query comprises one or more terms comparing event metadata to target values. For example, to select new block events:
tm.event = 'NewBlock'
Multiple terms can be combined with AND, for example to match the transaction event with a given hash, use:
tm.event = 'Tx' AND tx.hash = 'EA7B33F'
The comparison operators include =, <, <=, >, >=, and
CONTAINS. Operands may be strings (in single quotes), numbers, dates,
or timestamps. In addition, the EXISTS operator allows you to check
for the presence of an attribute regardless of its value.
Tendermint defines a tm.event attribute for all events. Transactions
are also assigned tx.hash and tx.height attributes. Other attributes
are provided by the application as ABCI Event records. The name of the
event in the query is formed by combining the type and attribute key
with a period. For example, given:
[]abci.Event{{
Type: "reward",
Attributes: []abci.EventAttribute{
{Key: "address", Value: "cosmos1xyz012pdq"},
{Key: "amount", Value: "45.62"},
{Key: "balance", Value: "100.390001"},
},
}}
the query may refer to the names"reward.address,"reward.amount, and
reward.balance, as in:
reward.address EXISTS AND reward.balance > 45
The node maintains a log of all events within an operator-defined time
window. The /events method returns the most recent items from the log
that match the query. Each item returned includes a cursor that marks
its location in the log. Cursors can be passed via the before and
after parameters to fetch events earlier in the log.
Subscribe for events via WebSocket.
/subscribeTo tell which events you want, you need to provide a query. query is a string, which has a form: "condition AND condition ..." (no OR at the moment). condition has a form: "key operation operand". key is a string with a restricted set of possible symbols ( \t\n\r\()"'=>< are not allowed). operation can be "=", "<", "<=", ">", ">=", "CONTAINS" AND "EXISTS". operand can be a string (escaped with single quotes), number, date or time.
Examples: tm.event = 'NewBlock' # new blocks tm.event = 'CompleteProposal' # node got a complete proposal tm.event = 'Tx' AND tx.hash = 'XYZ' # single transaction tm.event = 'Tx' AND tx.height = 5 # all txs of the fifth block tx.height = 5 # all txs of the fifth block
Tendermint provides a few predefined keys: tm.event, tx.hash and tx.height. Note for transactions, you can define additional keys by providing events with DeliverTx response.
import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/pubsub/query" )
abci.ResponseDeliverTx{ Events: []abci.Event{ { Type: "rewards.withdraw", Attributes: []abci.EventAttribute{ {Key: "address", Value: "AddrA", Index: true}, {Key: "source", Value: "SrcX", Index: true}, {Key: "amount", Value: "...", Index: true}, {Key: "balance", Value: "...", Index: true}, }, }, { Type: "rewards.withdraw", Attributes: []abci.EventAttribute{ {Key: "address", Value: "AddrB", Index: true}, {Key: "source", Value: "SrcY", Index: true}, {Key: "amount", Value: "...", Index: true}, {Key: "balance", Value: "...", Index: true}, }, }, { Type: "transfer", Attributes: []abci.EventAttribute{ {Key: "sender", Value: "AddrC", Index: true}, {Key: "recipient", Value: "AddrD", Index: true}, {Key: "amount", Value: "...", Index: true}, }, }, }, }
All events are indexed by a composite key of the form {eventType}.{evenAttrKey}. In the above examples, the following keys would be indexed:
- rewards.withdraw.address
- rewards.withdraw.source
- rewards.withdraw.amount
- rewards.withdraw.balance
- transfer.sender
- transfer.recipient
- transfer.amount
Multiple event types with duplicate keys are allowed and are meant to
categorize unique and distinct events. In the above example, all events
indexed under the key rewards.withdraw.address will have the following
values stored and queryable:
- AddrA
- AddrB
To create a query for txs where address AddrA withdrew rewards: query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA'")
To create a query for txs where address AddrA withdrew rewards from source Y: query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrA' AND rewards.withdraw.source = 'Y'")
To create a query for txs where AddrA transferred funds: query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrA'")
The following queries would return no results: query.MustParse("tm.event = 'Tx' AND transfer.sender = 'AddrZ'") query.MustParse("tm.event = 'Tx' AND rewards.withdraw.address = 'AddrZ'") query.MustParse("tm.event = 'Tx' AND rewards.withdraw.source = 'W'")
See list of all possible events here https://godoc.org/github.com/tendermint/tendermint/types#pkg-constants
For complete query syntax, check out https://godoc.org/github.com/tendermint/tendermint/libs/pubsub/query.
import rpchttp "github.com/tendermint/rpc/client/http"
import "github.com/tendermint/tendermint/types"
client, err := rpchttp.New("tcp://0.0.0.0:26657", "/websocket")
if err != nil {
// handle error
}
err = client.Start()
if err != nil {
// handle error
}
defer client.Stop()
ctx, cancel := context.WithTimeout(context.Background(), 1 * time.Second)
defer cancel()
query := "tm.event = 'Tx' AND tx.height = 3"
txs, err := client.Subscribe(ctx, "test-client", query)
if err != nil {
// handle error
}
go func() {
for e := range txs {
fmt.Println("got ", e.Data.(types.EventDataTx))
}
}()
NOTE: if you're not reading events fast enough, Tendermint might terminate the subscription.
Query Parameters
stringquery is a string, which has a form: "condition AND condition ..." (no OR at the moment). condition has a form: "key operation operand". key is a string with a restricted set of possible symbols ( \t\n\r\()"'=>< are not allowed). operation can be "=", "<", "<=", ">", ">=", "CONTAINS". operand can be a string (escaped with single quotes), number, date or time.
Responses
Unsubscribe from event on Websocket
/unsubscribeclient, err := rpchttp.New("tcp://0.0.0.0:26657", "/websocket")
if err != nil {
// handle error
}
err := client.Start()
if err != nil {
// handle error
}
defer client.Stop()
query := "tm.event = 'Tx' AND tx.height = 3"
err = client.Unsubscribe(context.Background(), "test-client", query)
if err != nil {
// handle error
}
Query Parameters
stringquery is a string, which has a form: "condition AND condition ..." (no OR at the moment). condition has a form: "key operation operand". key is a string with a restricted set of possible symbols ( \t\n\r\()"'=>< are not allowed). operation can be "=", "<", "<=", ">", ">=", "CONTAINS". operand can be a string (escaped with single quotes), number, date or time.
Responses
Unsubscribe from all events via WebSocket
/unsubscribe_allUnsubscribe from all events via WebSocket