When mx-notifier receives a SaveBlock frame from the node, it preprocesses all log events in the block into a flat list of NormalizedEvent structs. Each normalized event represents a single log entry emitted by a smart contract during block execution. The hub WebSocket and message broker publishers deliver these events to consumers.
NormalizedEvent
Field
Type
Description
address
bytes
The bech32-decoded address of the contract that emitted the event
identifier
bytes
The event identifier as raw bytes (e.g., UTF-8 encoding of "ESDTTransfer")
topics
[bytes]
Ordered list of event topics. Typically 2β4 items. Contents vary by event type (see below).
data
bytes
Additional unstructured event data. May be empty.
original_tx_hash
string
Hex hash of the user-submitted transaction that ultimately caused this event
source_tx_hash
string
Hex hash of the transaction or SCR that directly emitted this event. May differ from original_tx_hash in SCR chains.
order
usize
Position of this event within the block's full event list. Monotonically increasing per block.
Field notes
address
The raw bytes of the contract address. To display as bech32 (e.g., erd1qqq...), apply MultiversX bech32 encoding with HRP "erd".
Raw bytes of the event identifier string. In practice always valid UTF-8. To work with it as a string:
topics
Each entry in topics is a raw byte array. The meaning of each position is defined by the contract and event type β see the per-event-type tables below. The hub WebSocket transmits topics as base64-encoded strings.
original_tx_hash vs source_tx_hash
MultiversX contracts can generate Smart Contract Results (SCRs) β asynchronous messages sent to other contracts. An SCR is a transaction-like entity with its own hash. When a contract call generates an SCR and that SCR triggers a second contract that emits a log event:
original_tx_hash = hash of the user's original transaction (the root of the call chain)
source_tx_hash = hash of the specific SCR or transaction that directly emitted this event
For simple transactions with no SCRs, both fields are equal.
Use original_tx_hash to group all events from a single user action. Use source_tx_hash to trace the exact execution step that produced the event.
DEX swap events may carry additional topics beyond position 3 (token-out nonce, token-out amount, caller address). The exact layout depends on the DEX contract version. Use the data field for extended swap metadata.
addLiquidity / removeLiquidity
Position
Content
Encoding
0
First token identifier
UTF-8 bytes
1
First token nonce
Big-endian uint64 bytes
2
First token amount
Big-endian big integer bytes
3
Second token identifier
UTF-8 bytes
Decoding amounts and nonces
Token nonces and amounts are big-endian byte arrays with no fixed length (leading zero bytes are stripped). Decode them as arbitrary-precision integers:
Example: ESDTTransfer normalized event
The following shows a normalized event for a transfer of 1 WEGLD (1 * 10^18 base units) from a DEX contract to a user address.
Decoded field values:
Field
Decoded value
address
erd1qqqqqqqqqqqqqpgq... (DEX contract)
identifier
ESDTTransfer
topics[0]
WEGLD-bd4d79
topics[1]
0 (nonce = 0 for fungible token)
topics[2]
1000000000000000000 (1 WEGLD)
topics[3]
erd1... (recipient address)
order
17th event in the block
Event ordering
The order field is a block-scoped monotonically increasing integer. Events with lower order values were emitted earlier in block execution. Within a single user transaction, all events β including those from SCR-triggered sub-calls β are contiguous in order.
Event order is stable across redelivery and retries. Consumers can combine order with the block nonce to build a globally ordered event log.