Example: undelegate
To run this example:
- Clone the examples repository:
git clone https://github.com/throgxyz/examples.git - Run:
cargo run -p examples-staking --example undelegate
//! Reclaim previously delegated energy from another account.
//!
//! Undelegation is immediate for unlocked delegations. Locked delegations
//! must wait for the lock period to expire.
//!
//! Required env:
//! TRON_PRIVATE_KEY — hex private key of the delegating account
//! TRON_DELEGATE_TO — address that received the delegation
//!
//! Optional env:
//! TRON_API_KEY — TronGrid API key
//! TRON_FREEZE_SUN — amount to reclaim in sun (default: all available energy)
//!
//! ```bash
//! TRON_PRIVATE_KEY=<key> TRON_DELEGATE_TO=<addr> cargo run -p examples-staking --example undelegate
//! ```
use tronz::{
LocalSigner, ProviderBuilder, TRONGRID_NILE, TronProvider, TronSigner, Trx,
primitives::ResourceCode,
};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let key_hex = std::env::var("TRON_PRIVATE_KEY").expect("TRON_PRIVATE_KEY env var required");
let from_str = std::env::var("TRON_DELEGATE_TO").expect("TRON_DELEGATE_TO env var required");
let api_key = std::env::var("TRON_API_KEY").ok();
let signer = LocalSigner::from_hex(&key_hex)?;
let me = signer.address();
let receiver: tronz::Address = from_str.parse()?;
let provider = ProviderBuilder::new()
.with_recommended_fillers()
.with_signer(signer)
.maybe_api_key(api_key)
.on_grpc(TRONGRID_NILE)
.await?;
// ── Check current delegation ───────────────────────────────────────────────
let delegations = provider.get_delegated_resource(me, receiver).await?;
println!("=== Current delegation from {} to {} ===", me, receiver);
let delegated_energy =
delegations.iter().map(|d| d.energy_amount).fold(Trx::ZERO, |acc, a| acc + a);
if delegated_energy.as_sun() == 0 {
println!(" no energy delegated to {receiver}");
return Ok(());
}
println!(" energy delegated : {} TRX", delegated_energy);
// Check for lock expiry.
let locked = delegations.iter().any(|d| d.energy_expire_time_ms > 0);
if locked {
let expire_ms = delegations
.iter()
.filter_map(|d| (d.energy_expire_time_ms > 0).then_some(d.energy_expire_time_ms))
.min()
.unwrap_or(0);
println!(" WARNING: delegation is locked until {expire_ms} ms — undelegate may fail");
}
// ── Amount to reclaim ─────────────────────────────────────────────────────
let amount: Trx = std::env::var("TRON_FREEZE_SUN")
.ok()
.and_then(|s| s.parse::<i64>().ok())
.map(|sun| Trx::from_sun(sun).expect("valid sun amount"))
.unwrap_or(delegated_energy);
println!(" reclaiming : {} TRX", amount);
// ── Undelegate ────────────────────────────────────────────────────────────
let pending = provider
.undelegate_resource()
.resource(ResourceCode::Energy)
.amount(amount)
.from(receiver)
.send()
.await?;
println!("\n tx_id : 0x{}", hex::encode(pending.tx_id()));
println!(" waiting for confirmation…");
let info = pending.get_receipt().await?;
println!(" status : {:?}", info.status);
// ── Verify ───────────────────────────────────────────────────────────────
let after = provider.get_delegated_resource(me, receiver).await?;
let remaining = after.iter().map(|d| d.energy_amount).fold(Trx::ZERO, |acc, a| acc + a);
println!("\n=== After ===");
println!(" energy still delegated : {} TRX", remaining);
Ok(())
}Find the source code on GitHub here.
