use clap::Parser;
use hiero_sdk::{
AccountBalanceQuery, AccountCreateTransaction, AccountId, Client, Hbar, PrivateKey, Transaction, TransferTransaction
};
#[derive(Parser, Debug)]
struct Args {
#[clap(long, env)]
operator_account_id: AccountId,
#[clap(long, env)]
operator_key: PrivateKey,
#[clap(long, env, default_value = "testnet")]
hedera_network: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let _ = dotenvy::dotenv();
let args = Args::parse();
let client = Client::for_name(&args.hedera_network)?;
client.set_operator(args.operator_account_id, args.operator_key);
let exchange_key = PrivateKey::generate_ecdsa();
let user_key = PrivateKey::generate_ecdsa();
let exchange_account_id = AccountCreateTransaction::new()
.receiver_signature_required(true)
.set_key_without_alias(exchange_key.public_key())
.freeze_with(&client)?
.sign(exchange_key.clone())
.execute(&client)
.await?
.get_receipt(&client)
.await?
.account_id
.unwrap();
let user_account_id = AccountCreateTransaction::new()
.initial_balance(Hbar::new(5))
.set_key_without_alias(user_key.public_key())
.execute(&client)
.await?
.get_receipt(&client)
.await?
.account_id
.unwrap();
let mut transfer_txn = TransferTransaction::new();
transfer_txn
.hbar_transfer(user_account_id, Hbar::new(-2))
.hbar_transfer(exchange_account_id, Hbar::new(2))
.transaction_memo("https://some-exchange.com/user1/account1")
.freeze_with(&client)?
.sign(user_key);
let signed_txn_bytes = exchange_signs_transaction(exchange_key, &transfer_txn.to_bytes()?)?;
let mut signed_transfer_txn = Transaction::from_bytes(&signed_txn_bytes)?
.downcast::<TransferTransaction>()
.unwrap();
let transfer_amount = signed_transfer_txn
.get_hbar_transfers()
.values()
.copied()
.next()
.map(|it| if Hbar::ZERO >= it { it } else { -it });
println!("about to transfer {transfer_amount:?}...");
let transaction_response = signed_transfer_txn.execute(&client).await?;
transaction_response.get_receipt(&client).await?;
let sender_balance_after = AccountBalanceQuery::new()
.account_id(user_account_id)
.execute(&client)
.await?
.hbars;
let receipt_balance_after = AccountBalanceQuery::new()
.account_id(exchange_account_id)
.execute(&client)
.await?
.hbars;
println!("{user_account_id} balance = {sender_balance_after}");
println!("{exchange_account_id} balance = {receipt_balance_after}");
Ok(())
}
fn exchange_signs_transaction(
exchange_key: PrivateKey,
transaction_data: &[u8],
) -> hiero_sdk::Result<Vec<u8>> {
Transaction::from_bytes(transaction_data)?
.sign(exchange_key)
.to_bytes()
}