Contract events¶
Contract events provide a way for smart contracts to deliver live information to external applications. This mechanism allows off-chain applications to react to Mavryk contracts execution.
Note
Contract events should not be confused with log events, which are generated by the various Mavkit tools to include information about their execution in their own logs.
This page explains how events can be generated using specific support in the Michelson language. For using events in higher-level languages for smart contracts, consult their own documentation.
Emitting events¶
Contracts can create event emission operations by invoking the Michelson instruction EMIT
.
EMIT %tag ty
pops an item of type ty
off the stack and pushes an operation
onto the stack.
The type ascription ty
is special since annotations in ty
are preserved and eventually transmitted
in the event so that indexers have a choice to present the event body with appropriate labels.
Both the ty
type ascription and %tag
are optional.
If ty
is absent, this type is inferred from the type of the top element of the stack.
If %tag
is absent, no tag is attached to the event.
To actually send out the events, most importantly, the produced operation
s must be included in the list of
operations returned by the contract, along with TRANSFER_TOKEN
operations for example.
Upon successful contract execution, the events appearing in the resultant list of operations will be attached, in the order of appearance, to the transaction receipt. There, the events are made ready for consumption by services observing the chain.
Example¶
Suppose a contract wants to emit events with the following type:
or (nat %int) (string %str)
Then, this contract may generate an event emission operation with the following instructions:
PUSH string "right";
RIGHT nat;
EMIT %notify_client (or (nat %int) (string %str));
Note that the EMIT
instruction will emit an event with a tag notify_client
.
The additional tags int
and str
, allow indexers to recognise the two variants and present the values with the appropriate variant labels.
Retrieving events¶
Events successfully emitted can be read off from transaction results.
This is typically achieved by making JSON RPCs to the block service. It will return a list of operations, each including the event entries with the information above.
Here is a sample result from a call, corresponding to the example above.
{
"protocol": "ProtoALphaALphaALphaALphaALphaALphaALphaALphaDdp3zK",
"hash": "opNX59asPwNZGu2kFiHFVJzn7QwtyaExoLtxdZSm3Q3o4jDdSmo",
// ... fields elided for brevity
"contents": [
{
"kind": "transaction",
// ... fields elided for brevity
"metadata": {
// ... fields elided for brevity
"internal_operation_results": [
{
"kind": "event",
// ... fields elided for brevity
"source": "KT1M1ynE3YXkM7qLZoMppq6szMbBvxX9yQVL",
"nonce": 0,
"type": {
"prim": "or",
"args": [
{
"prim": "nat",
"annots": [
"%int"
]
},
{
"prim": "string",
"annots": [
"%str"
]
}
]
},
"tag": "notify_client",
"payload": {
"prim": "Right",
"args": [
{
"string": "right"
}
]
},
"result": {
"status": "applied",
"consumed_milligas": "1000000"
}
}
]
}
}
]
}
Note that the operation
produced by EMIT
does not constitute a call to any other contract.