Skip to main content

Working with Events

In the blockchain ecosystem, "events" are the on-chain log entries emitted by extrinsics — they're how the chain reports what actually happened: token transfers, collection creation, marketplace listing IDs, balance changes, and so on. Monitoring them is essential for any application that needs to react to state changes — for example, unlocking an in-game item the moment the user receives the corresponding NFT.

How events are exposed

Once a transaction has been included in a block, the platform exposes the extrinsic that carried it — and every event that extrinsic emitted — through the extrinsic field on the Transaction type:

{
extrinsic { # null until the transaction is included in a block
id # "blockNumber-extrinsicIndex", e.g. "11955161-2"
hash # the extrinsic hash
success # whether the extrinsic succeeded on-chain
events {
id # the event ID
name # human-readable name, e.g. "MultiTokens Collection Created"
collectionId # the related collection ID, when the event concerns one
tokenId # the related token ID (canonical "collectionId-tokenId" form)
data # trimmed JSON payload with the event's key values
}
}
}

A few things to know about the fields:

  • name is the pallet and event name with spaces — MultiTokens Collection Created, MultiTokens Minted, Marketplace Listing Created, Balances Transfer, and so on. Note that on-chain event names are conventionally written in dotted form (MultiTokens.CollectionCreated), including elsewhere in these docs — the platform's name field is the same event with the words spaced out, so match against the spaced form when filtering.
  • collectionId / tokenId are filled in when the event relates to a specific collection or token, so you can match events to your assets without parsing data.
  • data carries the event's key values as JSON — the IDs your application usually needs. For example, MultiTokens Collection Created carries {"collectionId": "124587"}, MultiTokens Minted carries {"amount": "1"}, and Marketplace Listing Created carries the full listing (id, price, amount, type). Events whose meaning is fully captured by the other fields have an empty data payload.
  • The platform surfaces the events relevant to the action itself; low-level bookkeeping events (fee payments and similar) are not included.

Reading a transaction's events

The flow after submitting any CreateTransaction mutation is:

  1. Wait for the transaction to reach FINALIZED — either poll GetTransaction(uuid:), or subscribe to the TransactionStateChanged WebSocket event to be notified the moment the state changes. While the transaction is still PENDING or awaiting inclusion in a block, extrinsic is null.
  2. Check extrinsic.success to confirm the on-chain outcome (a failed extrinsic emits no events).
  3. Read extrinsic.events and pick out the ones you care about by name.
query GetTransactionEvents($uuid: String!) {
GetTransaction(
network: CANARY
chain: MATRIX
uuid: $uuid
) {
state
extrinsic {
hash
success
events {
id
name
collectionId
tokenId
data
}
}
}
}

Variables:

{
"uuid": "06303d39-6ba9-4c81-8500-55bcca9e9512"
}

Example: picking up a new collection ID

Some values only exist once the chain executes the transaction — the collectionId assigned by createCollection is the classic case. Events are how you read them.

Submitting the collection creation returns a transaction in PENDING state, with no extrinsic yet:

{
"data": {
"CreateTransaction": {
"uuid": "06303d39-6ba9-4c81-8500-55bcca9e9512",
"action": "MultiTokens.create_collection",
"state": "PENDING",
"extrinsic": null
}
}
}

Polling GetTransactionEvents (the query above) with that uuid eventually returns FINALIZED, and the new collection's ID appears in the MultiTokens Collection Created event — both on the event itself and in its data payload:

{
"data": {
"GetTransaction": {
"state": "FINALIZED",
"extrinsic": {
"hash": "0xb3a2a733cf24df07fbbbffdf4447959ce66fd78ed46bc78e10c4991004b43b3b",
"success": true,
"events": [
{
"id": "1234567-2",
"name": "MultiTokens Attribute Set",
"collectionId": "124587",
"tokenId": null,
"data": []
},
{
"id": "1234567-3",
"name": "MultiTokens Collection Created",
"collectionId": "124587",
"tokenId": null,
"data": {
"collectionId": "124587"
}
}
]
}
}
}
}

The same pattern applies to every chain-assigned value: the token ID in MultiTokens Token Created after a mint into a new token, the listing in Marketplace Listing Created after createListing, the group ID after createTokenGroup, and so on.

Reacting to transfers

Transfer-style events (MultiTokens Transferred, MultiTokens Minted, Balances Transfer) carry the related collectionId / tokenId, which is usually all you need to react in-game — e.g. unlocking the item that corresponds to the token the player just received.

Other ways to look events up

Events hang off the extrinsic, so any query that returns an Extrinsic returns them too:

You can also follow your transactions in the Platform UI: the Transactions page shows each transaction's state and extrinsic hash as it moves on-chain.

Skip the polling

The platform pushes TransactionStateChanged and other events to your application over WebSocket in real time, removing the need to poll — see WebSocket Events for the full reference.