use std::str::FromStr;
use hedera::{
AccountBalanceQuery, AccountCreateTransaction, AccountId, BatchTransaction, Client, Hbar, PrivateKey, TransferTransaction
};
#[tokio::main]
#[ignore] async fn main() -> hedera::Result<()> {
let client = Client::for_testnet();
let operator_key = PrivateKey::from_str_ed25519(
"302e020100300506032b657004220420a869f4c6191b9c8c99933e7f6b6611711737e4b1a1a5a4cb5370e719a1f6df98"
)?;
let operator_account = AccountId::from_str("0.0.1001")?;
client.set_operator(operator_account, operator_key);
println!("BatchTransaction Example");
println!("========================");
let batch_key = PrivateKey::generate_ed25519();
println!("Generated batch key: {}", batch_key.public_key());
let alice_key = PrivateKey::generate_ed25519();
let alice = create_account(&client, alice_key.public_key(), Hbar::new(5)).await?;
println!("Created Alice account: {}", alice);
let bob_key = PrivateKey::generate_ed25519();
let bob = create_account(&client, bob_key.public_key(), Hbar::new(3)).await?;
println!("Created Bob account: {}", bob);
println!("\nPreparing batch transactions...");
let mut alice_transfer = TransferTransaction::new();
alice_transfer
.hbar_transfer(alice, Hbar::new(-1)) .hbar_transfer(operator_account, Hbar::new(1));
alice_transfer.freeze_with(&client)?;
alice_transfer.set_batch_key(batch_key.public_key().into());
alice_transfer.sign(alice_key.clone());
let mut bob_transfer = TransferTransaction::new();
bob_transfer
.hbar_transfer(bob, Hbar::new(-2)) .hbar_transfer(operator_account, Hbar::new(2));
bob_transfer.freeze_with(&client)?;
bob_transfer.set_batch_key(batch_key.public_key().into());
bob_transfer.sign(bob_key.clone());
println!("\nBalances before batch execution:");
print_balance(&client, "Alice", alice).await?;
print_balance(&client, "Bob", bob).await?;
print_balance(&client, "Operator", operator_account).await?;
println!("\nExecuting batch transaction...");
let mut batch = BatchTransaction::new();
batch.add_inner_transaction(alice_transfer.into())?;
batch.add_inner_transaction(bob_transfer.into())?;
batch.freeze_with(&client)?;
batch.sign(batch_key);
let response = batch.execute(&client).await?;
let receipt = response.get_receipt(&client).await?;
println!("Batch transaction executed successfully!");
println!("Transaction ID: {}", response.transaction_id);
println!("Status: {:?}", receipt.status);
println!("\nBalances after batch execution:");
print_balance(&client, "Alice", alice).await?;
print_balance(&client, "Bob", bob).await?;
print_balance(&client, "Operator", operator_account).await?;
println!("\nInner transaction IDs:");
for (i, tx_id) in batch.get_inner_transaction_ids().iter().enumerate() {
if let Some(id) = tx_id {
println!("Transaction {}: {}", i + 1, id);
}
}
println!("\nBatchTransaction example completed successfully!");
Ok(())
}
async fn create_account(
client: &Client,
public_key: hedera::PublicKey,
initial_balance: Hbar,
) -> hedera::Result<AccountId> {
let response = AccountCreateTransaction::new()
.set_key_without_alias(public_key)
.initial_balance(initial_balance)
.execute(client)
.await?;
let receipt = response.get_receipt(client).await?;
receipt.account_id.ok_or_else(|| {
hedera::Error::TimedOut(Box::new(hedera::Error::GrpcStatus(
tonic::Status::not_found("account_id not found in receipt"),
)))
})
}
async fn print_balance(client: &Client, name: &str, account_id: AccountId) -> hedera::Result<()> {
let balance = AccountBalanceQuery::new()
.account_id(account_id)
.execute(client)
.await?;
println!("{}: {} HBAR", name, balance.hbars);
Ok(())
}