SolidityNode provider
A TRON SolidityNode serves solidified state — blocks and receipts confirmed
by 2/3+ of the super representatives, which can no longer be reorged. Read it
through a SolidityProvider, a read-only companion to the FullNode
TronProvider.
use tronz::{SolidityProvider, TRONGRID_MAINNET_SOLIDITY};Read-only by construction
SolidityProvider has no signer, no fillers, and no
broadcast path, so trying to mutate state through it is a compile-time error —
not a runtime failure. It talks to the WalletSolidity service, which lives on a
different endpoint from the FullNode:
| Network | FullNode (TronProvider) | SolidityNode (SolidityProvider) |
|---|---|---|
| Mainnet | TRONGRID_MAINNET | TRONGRID_MAINNET_SOLIDITY |
| Nile | TRONGRID_NILE | TRONGRID_NILE_SOLIDITY |
| Local TRE | http://127.0.0.1:50051 | http://127.0.0.1:50052 |
Because it only sees irreversible state, a SolidityNode lags the FullNode head by the solidification window (~19 blocks).
Connecting
use tronz::{SolidityProvider, TRONGRID_MAINNET_SOLIDITY};
let solidity = SolidityProvider::connect(TRONGRID_MAINNET_SOLIDITY).await?;
let head = solidity.get_now_block().await?;
println!("solidified head: {}", head.number);use tronz::SolidityProvider;
let solidity = SolidityProvider::connect("http://127.0.0.1:50052").await?;See Local TRE node for the Docker command and SDK end-to-end test setup.
Use SolidityProvider::builder() when you need custom timeouts, retries,
failover endpoints, or a TronGrid API key:
use core::time::Duration;
use tronz::{SolidityProvider, TRONGRID_MAINNET_SOLIDITY};
let solidity = SolidityProvider::builder()
.with_request_timeout(Duration::from_secs(10))
.maybe_api_key(api_key)
.connect(TRONGRID_MAINNET_SOLIDITY)
.await?;What you can read
The read surface mirrors the FullNode's, restricted to what WalletSolidity
exposes: blocks (get_now_block, get_block_by_number), accounts
(get_account), transactions and receipts (get_transaction,
get_transaction_info, get_transaction_info_by_block_num,
get_transaction_count_by_block_num), contract reads
(trigger_constant_contract, estimate_energy), and — since 0.4.1 — the
governance and stake/delegation queries (list_witnesses,
get_paginated_now_witness_list, get_delegated_resource_index,
get_can_delegate_max, get_available_unfreeze_count,
get_can_withdraw_unfreeze_amount).
let account = solidity.get_account(address).await?;
println!("solidified balance: {} TRX", account.balance);Typed contract reads
SolidityProvider implements ContractReadProvider, so the same typed handles
you use on a FullNode — .trc20(), .trc721(), tron_sol! bindings, and
ContractInstance — bind to it and read solidified state. No manual
trigger_constant_contract needed:
use tronz::contract::Trc20Ext;
let balance = solidity.trc20(usdt).balance_of(who).await?;See the typed TRC20 example. For a raw constant call, see the constant-call example.
Waiting for finality
The provider polls for solidification. wait_for_transaction returns the receipt
once the transaction is irreversible; wait_for_success additionally fails if it
solidified but reverted:
let receipt = solidity.wait_for_success(tx_id).await?;
println!("solidified in block {}", receipt.block_number);Bridging from a broadcast
FullNode inclusion can still be reorged; solidified state cannot. A
PendingTransaction returned from a FullNode .send() can bridge straight to
finality against a SolidityProvider:
let pending = full.send_trx().to(to).amount(amount).send().await?;
// Broadcast on the FullNode, then wait for irreversible success.
let receipt = pending
.require_success()
.get_solidified_receipt(solidity)
.await?;
println!("final in block {}", receipt.block_number);See the runnable SolidityNode examples.
