Example: trc20_decode_transfer_event
To run this example:
- Clone the examples repository:
git clone https://github.com/throgxyz/examples.git - Run:
cargo run -p examples-trc20 --example trc20_decode_transfer_event
//! Decode `Transfer(address,address,uint256)` logs from a confirmed receipt.
//!
//! TRC20 events are EVM-compatible. The `Transfer` event signature hash is the
//! same as ERC-20: `keccak256("Transfer(address,address,uint256)")`.
//!
//! This example fetches a known transaction and decodes all Transfer events in
//! its receipt using the static `sol!` binding from `tronz_contract`.
//!
//! No private key required (read-only).
//!
//! Required env:
//! TRON_TX_ID — hex transaction id that emitted Transfer events
//!
//! Optional env:
//! TRON_API_KEY — TronGrid API key
//!
//! ```bash
//! TRON_TX_ID=<txid> cargo run -p examples-trc20 --example trc20_decode_transfer_event
//! ```
// Re-use the static ABI binding from tronz_contract.
use tronz::{
ProviderBuilder, TRONGRID_NILE, TronProvider,
contract::{SolEvent, decode_logs, trc20::ITRC20},
primitives::B256,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let tx_id_hex = std::env::var("TRON_TX_ID").expect("TRON_TX_ID env var required");
let api_key = std::env::var("TRON_API_KEY").ok();
let tx_id_bytes = hex::decode(tx_id_hex.trim_start_matches("0x"))?;
let tx_id: B256 = B256::from_slice(&tx_id_bytes);
let provider = ProviderBuilder::new().maybe_api_key(api_key).on_grpc(TRONGRID_NILE).await?;
// ── Fetch receipt ─────────────────────────────────────────────────────────
let info = provider
.get_transaction_info(tx_id)
.await?
.ok_or_else(|| anyhow::anyhow!("transaction not found or not yet confirmed"))?;
println!("=== Receipt ===");
println!(" tx_id : 0x{}", hex::encode(tx_id));
println!(" status : {:?}", info.status);
println!(" logs : {}", info.logs.len());
// ── Decode Transfer events ────────────────────────────────────────────────
//
// `decode_logs::<E>` skips logs that don't match and returns Results for
// those that do. The `Transfer` type was generated by `sol!` in the
// tronz_contract crate.
let transfer_topic0 = ITRC20::Transfer::SIGNATURE_HASH;
println!("\n=== Transfer event signature ===");
println!(" topic0 : 0x{}", hex::encode(transfer_topic0));
let transfers: Vec<_> =
decode_logs::<ITRC20::Transfer>(&info.logs).collect::<Result<_, _>>()?;
if transfers.is_empty() {
println!("\n no Transfer events in this transaction");
return Ok(());
}
println!("\n=== Transfer events ({}) ===", transfers.len());
for (i, t) in transfers.iter().enumerate() {
// The `from` / `to` fields are `alloy_primitives::Address` (20 bytes).
// Convert to tronz::Address to display in base58check.
let from: tronz::Address = t.from.into();
let to: tronz::Address = t.to.into();
println!(" [{i}] from : {from}");
println!(" to : {to}");
println!(" value : {}", t.value);
}
Ok(())
}Find the source code on GitHub here.
