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.