Event subscription

Four ways to receive TRON on-chain events — TronGrid HTTPS, TronWeb, the Fullnode's built-in ZeroMQ publisher, or self-hosted plugins (Kafka / MongoDB) — plus the V1.0 / V2.0 event service framework and the seven event trigger types.

📘

Prerequisites

A TRON Fullnode produces a continuous stream of on-chain activity — every block, every transaction, every smart-contract log. Event subscription is the mechanism by which an application receives that stream. There are multiple ways to access it, depending on how much infrastructure you want to operate and whether you need historical backfill in addition to real-time push.

How to access events

MethodBest forOperates locally?Historical backfill
TronGrid (hosted HTTPS query)Front-ends, lightweight integrationsNo — managed serviceYes (queryable by tx / block)
TronWeb (JavaScript SDK)Browser and Node.js appsNo — wraps TronGridYes (Mainnet + testnets; private chains not supported)
Built-in ZeroMQ (Fullnode publisher)Dev work, a single in-network consumerYes — needs a FullnodeNo — real-time only
Self-hosted plugin (Kafka / MongoDB)Indexers, analytics pipelines, durable streamsYes — needs a Fullnode + plugin + storageYes (with V2.0 framework)

The first two require no infrastructure beyond what your application already runs. The last two require operating a TRON Fullnode but give you direct access to the event stream without provider rate limits.

  • TronGrid — see Get events by transaction ID and TronGrid V1 API overview. TronGrid formats event-plugin data as extension APIs and exposes them through hosted HTTPS endpoints.
  • TronWeb — JavaScript SDK with built-in event helpers. See the TronWeb event API. Works on Mainnet and testnets; not available for private chains.
  • Built-in ZeroMQ — TRON Fullnodes ship a built-in ZeroMQ publisher (TIP-28), so no plugin install is needed. See ZeroMQ event plugin.
  • Self-hosted plugins — durable transports backed by Kafka or MongoDB. The rest of this page focuses on these.

Event service framework

When you run a self-hosted plugin, the Fullnode's event service framework is what fetches events from the chain, wraps them, queues them, and pushes them into your plugin for asynchronous storage. Two framework versions exist; the choice affects whether historical backfill is available.

VersionReal-time pushesHistorical backfillDefault
V1.0Yes — events fire as new blocks are processedNo — only events produced from the moment the node startsYes (when event.subscribe.version is unset)
V2.0YesYes — events from a configured starting height are replayed before the live streamOpt-in via event.subscribe.version = 1

V2.0 was introduced to let indexers bootstrap from a specific historical block rather than only follow the chain head. For deeper background and version-selection guidance, see the Event service framework V2.0 introduction.

Migrating V1.0 → V2.0

Both versions use the same plugin binaries and the same subscription configuration; migration is mostly a one-line config flip.

  1. Update the plugin. V2.0 historical sync can produce high-volume bursts; older plugin builds may run out of memory. Download the latest from event-plugin releases or build from source:

    git clone https://github.com/tronprotocol/event-plugin.git
    cd event-plugin
    ./gradlew build
  2. Enable V2.0 in config.conf:

    event.subscribe.version = 1
  3. Keep your subscription configuration unchanged. The topics, filter, path, server, and dbconfig blocks all carry over from V1.0.

  4. (Optional) Configure historical backfill start height:

    event.subscribe.startSyncBlockNum = <block_height>
    • startSyncBlockNum <= 0 — backfill disabled; behavior matches V1.0 real-time.
    • startSyncBlockNum > 0 — backfill enabled; events from that height are replayed before the live stream starts.
  5. Restart the Fullnode with --es. Historical events replay first, then the live stream takes over.

🚧

Verify startSyncBlockNum before restart.

A height below your consumer's last-seen point produces duplicates; a height above produces gaps. This is the most common source of post-migration data inconsistencies.


Event types

A Fullnode emits seven trigger types. Each can be independently enabled in the plugin's topics block. The triggerName values are fixed identifiers; only the consumer-side topic name (Kafka topic or MongoDB collection) is customizable.

triggerNameCarriesTypical use
blockNewly produced block headersBlock-height monitors, head trackers
transactionTransactions in newly produced blocksTransaction indexers, mempool analyzers
contracteventDecoded contract events (parsed against ABI)Application back-ends consuming events as structured records
contractlogRaw contract logs (topics + data)DeFi indexers, NFT trackers handling raw logs
soliditySolidified block headers (≥19-SR confirmed)Exchanges, bridges — anything needing finality before acting
solidityeventDecoded contract events on solidified blocksSame as contractevent but post-finality
soliditylogRaw contract logs on solidified blocksSame as contractlog but post-finality
📘

Event subscription resource cost

Subscribing to many trigger types simultaneously raises the Fullnode's CPU and memory cost. Pick the smallest set that meets your application's needs — for most use cases, one or two.

Trigger payloads

The payloads carry these fields:

Block / Solidity trigger

timeStamp                     block timestamp
triggerName                   "blockTrigger" or "solidityTrigger"
blockNumber                   block height
blockHash                     block ID
transactionSize               number of transactions in the block
latestSolidifiedBlockNumber   most recent solidified height
transactionList               list of transaction hashes

Transaction trigger

blockHash                     block ID
blockNumber                   block height
energyUsage                   total Energy consumed by the transaction
energyFee                     TRX burned to cover Energy
originEnergyUsage             Energy paid by the contract deployer
energyUsageTotal              total Energy (caller + deployer + burn)

Contract event trigger / solidityevent

transactionId                 transaction hash
contractAddress               contract address
callerAddress                 address that invoked the contract
blockNumber                   containing block height
blockTimestamp                block timestamp
eventSignature                Solidity event signature
topicMap                      map of indexed topics (name → value)
data                          non-indexed event data (Solidity representation)
removed                       true if log was removed (reorg)

Contract log trigger / soliditylog

transactionId                 transaction hash
contractAddress               contract address
callerAddress                 address that invoked the contract
blockNumber                   containing block height
blockTimestamp                block timestamp
contractTopics                list of raw 32-byte topics
data                          raw event data
removed                       true if log was removed (reorg)

For the canonical specification, see TIP-12 — Event subscription.

Filter syntax

The filter block narrows contract-event and contract-log streams. It does not apply to block / transaction triggers.

FieldMeaning
fromblock"", "earliest", or a specific height; lower bound (inclusive)
toblock"", "latest", or a specific height; upper bound (inclusive)
contractAddressList of contract addresses; empty list matches all
contractTopicList of event topic hashes; empty list matches all

Self-hosted plugin architecture

For the self-hosted path, the Fullnode loads a plugin (a Java JAR) at start-up; the plugin handles the transport to your chosen message system or storage.

┌────────────────┐      events       ┌──────────────┐      transport      ┌──────────────┐
│  TRON Fullnode │  ───────────────▶ │   Plugin     │  ────────────────▶  │  Consumer    │
│  (java-tron)   │   (in-process)    │  (.jar)      │  (ZMQ/Kafka/Mongo)  │  (your app)  │
└────────────────┘                   └──────────────┘                     └──────────────┘

Two plugin implementations ship as reference:

PluginTransportBest forDoc
KafkaApache Kafka topicsDurable streams, multiple consumers, replay by offsetKafka plugin
MongoDBMongoDB collectionsIndexed event storage, ad-hoc queriesMongoDB plugin

The Fullnode's built-in ZeroMQ publisher serves the same role for cases where you don't want to operate a separate plugin or storage layer — see ZeroMQ event plugin.

You can write your own plugin against the java-tron event SPI — the entry point is the org.tron.common.logsfilter.IPluginEventListener interface. Kafka and MongoDB are reference implementations; the event-plugin source is the template.

Choosing a plugin

  • ZeroMQ — lowest setup cost; no persistence; best for development or a single in-network consumer.
  • Kafka — durable; supports replay by offset; multiple downstream consumers; best when you already operate Kafka.
  • MongoDB — indexed storage; pairs with the optional TRON Event Query HTTP service for ad-hoc lookups.

Enabling event subscription

Same flow regardless of plugin:

  1. Build or download the plugin JAR (or the latest event-plugin release).
  2. Place the JAR somewhere readable by the Fullnode.
  3. Add the event.subscribe block to config.conf — set path to the JAR, server to the transport endpoint, and topics / filter to your subscription.
  4. Restart the Fullnode with --es.

Per-plugin specifics (Kafka topic creation, MongoDB account provisioning, etc.) live in the per-plugin docs.

📘

Resource cost.

Event subscription adds CPU and memory load to the Fullnode. For high-throughput SR nodes, consider running event subscription on a separate dedicated Fullnode that syncs the same chain, so event processing does not compete with the consensus thread.


Related resources