use algonaut::Algod;
use algonaut::abi::abi_type::AbiValue;
use algonaut::atomic::{AbiMethodReturnValue, AtomicGroupBuilder};
use algonaut::transaction::Signer;
use algonaut::transaction::account::Account;
use dotenv::dotenv;
use std::env;
use std::error::Error;
use std::sync::Arc;
#[macro_use]
extern crate log;
algonaut::contract!("tests/fixtures/vault.arc56.json");
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
dotenv().ok();
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info")).init();
let algod_url = env::var("ALGOD_URL")?;
let algod = Algod::new(&algod_url, &env::var("ALGOD_TOKEN")?)?;
let alice = Account::from_mnemonic(&env::var("ALICE_MNEMONIC")?)?;
let sender = alice.address();
let signer: Arc<dyn Signer> = Arc::new(alice);
let params = algod.suggested_params().await?;
info!("connected to algod at {algod_url} as {sender}");
info!("deploy: compiling the contract's TEAL and submitting app-create");
let vault = Vault::deploy(&algod, sender, Arc::clone(&signer), ¶ms).await?;
info!("deploy: Vault is live as app id {}", vault.app_id().0);
info!(r#"call: grouping store(2,3) + scale((4,5),10) + store_wrapped((6,7),"demo")"#);
let store = vault
.store(Pair {
first: 2,
second: 3,
})
.build(¶ms);
let scale = vault
.scale(
Pair {
first: 4,
second: 5,
},
10,
)
.build(¶ms);
let wrapped = vault
.store_wrapped(Wrapper {
inner: Pair {
first: 6,
second: 7,
},
label: "demo".to_owned(),
})
.build(¶ms);
let executed = AtomicGroupBuilder::new()
.add_method_call(store)
.add_method_call(scale)
.add_method_call(wrapped)
.build()?
.sign()
.await?
.execute(&algod)
.await?;
info!(
"call: group confirmed in round {}",
executed.confirmed_round.unwrap_or_default()
);
if let Some(scale_result) = executed.method_results.get(1) {
match &scale_result.return_value {
Ok(AbiMethodReturnValue::Some(value)) => info!("call: scale returned {value:?}"),
Ok(AbiMethodReturnValue::Void) => {}
Err(e) => warn!("call: scale return decode failed: {e:?}"),
}
}
let _incr = vault.incr(None).build(¶ms);
let _incr_override = vault.incr(Some(5)).build(¶ms);
info!("default: built incr(None) (uses literal 1) and incr(Some(5)) (overrides it)");
let _opt_in = vault.enroll().opt_in().build(¶ms);
info!("lifecycle: built enroll().opt_in() — OnComplete set to OptIn from the declared action");
info!("simulate: dry-running get_pair (read-only, nothing submitted)");
let simulated = vault.get_pair().simulate(&algod, ¶ms).await?;
if let Some(result) = simulated.method_results.first() {
match &result.return_value {
Ok(AbiMethodReturnValue::Some(value)) => info!("simulate: get_pair returned {value:?}"),
Ok(AbiMethodReturnValue::Void) => {}
Err(e) => warn!("simulate: get_pair decode failed: {e:?}"),
}
}
if let Some(total) = vault.global_total(&algod).await? {
info!("state: global `total` = {total:?}");
}
match vault.global_owner(&algod).await? {
Some(owner) => info!("state: global `owner` = {owner:?}"),
None => info!("state: global `owner` is unset"),
}
if let Some(first) = executed.method_results.first()
&& let Some(logs) = &first.transaction_info.logs
{
let raw: Vec<Vec<u8>> = logs.iter().map(|log| log.0.clone()).collect();
let events = Vault::decode_events(&raw);
info!(
"events: decoded {} from the first call's logs",
events.len()
);
for event in events {
match event {
VaultEvent::Counted(AbiValue::Array(fields)) => {
info!("events: Counted -> {fields:?}");
}
other => info!("events: {other:?}"),
}
}
}
info!("done");
Ok(())
}