Skip to content
Logo

Fillers

A filler automatically populates fields on a transaction before it is signed and broadcast — things the caller shouldn't have to compute by hand. tronz borrows this pattern directly from alloy: you stack fillers on the ProviderBuilder, and they run on every .send().

Why fillers exist

A TRON transaction needs more than just "to" and "amount". It must reference a recent block (TAPOS, for replay protection and expiry), and contract operations need a fee_limit. The node endpoints that build the currently supported transactions already fill TAPOS for you, so the recommended set installs an EnergyFiller that estimates contract energy and derives fee_limit. with_tapos() remains available for locally referenced transactions.

For almost any read/write provider, start here:

use tronz::{LocalSigner, ProviderBuilder, TRONGRID_NILE};
 
let provider = ProviderBuilder::new()
    .with_signer(signer)
    .connect_grpc(TRONGRID_NILE)
    .await?;

ProviderBuilder::new() already calls with_recommended_fillers(), which adds:

let builder = ProviderBuilder::default()
    .with_energy(EnergyFiller::new());

It does not add the TAPOS filler: the node endpoints that build the currently supported transactions already fill TAPOS. Add with_tapos() explicitly if you build transactions that need tronz to fill those fields.

Available fillers

FillerAdded byFills
TAPOSwith_tapos()The reference block hash + expiration (required before broadcast)
Energynew(), with_recommended_fillers(), or with_energy(...)Estimates energy and derives fee_limit with a safety margin
Fee limitwith_fee_limit(Trx)Sets a fixed default fee_limit
Walletwith_signer(s), wallet(w), or strict_wallet(w)Selects a credential and signs the transaction id

The wallet is itself part of the filler chain — that's why a provider's ability to .send() is encoded in its type. wallet() prefers the owner's key and falls back to the wallet's default key, which supports active permissions owned by another account. strict_wallet() rejects a transaction when the wallet has no key matching its owner.

Choosing a fee limit per call

The fee-limit filler sets a default. The fee limit is the maximum TRX you'll spend if you don't have enough staked energy/bandwidth. Override it when needed via the transaction builders (see Transactions), or set a different default:

use tronz::{ProviderBuilder, Trx, TRONGRID_NILE};
 
let provider = ProviderBuilder::new()
    .with_fee_limit("100".parse()?)  // higher cap for heavy contract calls
    .connect_grpc(TRONGRID_NILE)
    .await?;

Estimating energy first

For contract calls you can estimate the energy cost before sending, so you can pick a sensible fee_limit — analogous to estimate_gas in alloy:

let energy = provider.estimate_energy(params).await?;