<p align="center">
<img src="assets/rocket-solid.png" width="128" height="128">
</p>
# Rust `algonaut`
[](https://crates.io/crates/algonaut)
[](https://docs.rs/algonaut)
[](https://github.com/manuelmauro/algonaut/actions/workflows/general.yml)
[](#license)
A Rust SDK for the [Algorand](https://www.algorand.com/) blockchain. Pre-1.0 — the API is stabilising but still moves between minor versions.
## Highlights
- Async clients for `algod` v2, `kmd` v1, and `indexer` v2
- One-call transaction builders for payments, asset config / transfer / freeze / clawback, application calls, key registration, and state proofs
- A typestate `AtomicGroupBuilder` — bundle transactions and ARC-4 ABI calls, then `simulate`, `sign`, and `execute`
- Typed contract clients generated at compile time from an ARC-4 ABI or a full ARC-56 app spec (`contract!`) — typed-struct args, a `deploy` constructor, state readers, and ARC-28 events
- An open, async `Signer` trait: `Account` out of the box, or plug in an HSM, remote KMS, or WalletConnect
- TEAL compile / disassemble + V3 source-map decoder
- Cucumber acceptance suite that exercises the algorand-sdk-testing harness end-to-end
## Quickstart: an atomic group
Generate a typed client from an ARC-56 app spec with `contract!`, `deploy` it
straight from the spec, call a method with a typed-struct argument, dry-run the
group with `simulate`, then `sign` and `execute` the very same group — the
headline `algonaut` flow. Raw transactions (payments, asset ops) drop into the
same group via `add_transaction`. See
[`examples/contract_arc56.rs`](./examples/contract_arc56.rs) for the fully annotated
version (events, defaults, lifecycle actions, and more).
```rust
use algonaut::Algod;
use algonaut::atomic::AtomicGroupBuilder;
use algonaut::transaction::Signer;
use algonaut::transaction::account::Account;
use std::sync::Arc;
use std::{env, error::Error};
// `contract!` reads an ARC-56 "Extended App Description" at compile time and
// generates a typed `Vault` client: a `deploy` constructor that compiles the
// spec's TEAL, the named `Pair` struct as a typed argument, one builder per ABI
// method, and `global_*` readers that decode state per the spec's declared types.
algonaut::contract!("contracts/vault.arc56.json");
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
let algod = Algod::new(&env::var("ALGOD_URL")?, &env::var("ALGOD_TOKEN")?)?;
let alice = Account::from_mnemonic(&env::var("ALICE_MNEMONIC")?)?;
let sender = alice.address();
// A signer is shared as `Arc<dyn Signer>`: `Account` here, but any HSM,
// remote KMS, or WalletConnect impl drops in the same way.
let signer: Arc<dyn Signer> = Arc::new(alice);
let params = algod.suggested_params().await?;
// Deploy straight from the spec: `deploy` compiles the contract's TEAL,
// submits the app-create with the declared state schema, and hands back a
// client bound to the new app id — no hand-managed `AppId`.
let vault = Vault::deploy(&algod, sender, Arc::clone(&signer), ¶ms).await?;
println!("deployed Vault as app {}", vault.app_id().0);
// `Pair` is the Rust struct generated for the ARC-56 `Pair`; `store` won't
// compile unless the spec declares it and the field types line up.
let store = vault.store(Pair { first: 2, second: 3 }).build(¶ms);
let group = AtomicGroupBuilder::new().add_method_call(store).build()?;
// `simulate` borrows the group, so we dry-run it before touching a key; then
// `sign` (async — a wallet may await approval) and `execute` the same group.
group.simulate(&algod).await?;
let outcome = group.sign().await?.execute(&algod).await?;
println!("confirmed in round {:?}", outcome.confirmed_round);
// Global state, decoded per the key's declared ARC-56 type.
println!("total = {:?}", vault.global_total(&algod).await?);
Ok(())
}
```
## What's new since 0.4.2
`algonaut` rested at `0.4.2` for years; the `0.5`–`0.8` line is a ground-up
modernization, and the example above is the API as it stands today:
- **0.5** — Rust 2024 edition (MSRV 1.85); `ring` swapped for `ed25519-dalek`, so `wasm32` builds need no C toolchain; workspace-wide dependency refresh; `lefthook` + `make ci`.
- **0.6** — `simulate` and dry-run request builders, a TEAL V3 source-map decoder, and domain types that serialize to both JSON and msgpack.
- **0.7** — identifier newtypes (`AppId`, `AssetId`, `TransactionId`) at the client boundary, block / account-resource / ledger-delta endpoints, and msgpack response decoding.
- **0.8** — an open, async `Signer` trait (HSM / remote KMS / WalletConnect friendly), the typestate `AtomicGroupBuilder` shown above, Cargo feature gates for clients (`algod`, `indexer`, `kmd`), and structured error types with full source-chaining.
- **0.9** — typed contract clients generated at compile time from a full **ARC-56** app spec: `contract!("app.arc56.json")` emits a `deploy` constructor (compiling the spec's TEAL or using precompiled `byteCode`), typed struct / tuple / array / reference / transaction method arguments, `global` / `local` / `box` / `map` state readers decoded per their declared ARC-56 types, ARC-28 event decoding, literal and sourced argument defaults, and a read-only `simulate` path — building on the ARC-4 `contract!` macro also introduced in this line. The earlier `abi_call!` / `abi_method!` macros are removed in its favour.
Each decision is recorded as an ADR under [`docs/adr/`](./docs/adr/); [CHANGELOG.md](./CHANGELOG.md) has the full entry-by-entry history.
## Workspace layout
| Crate | Purpose |
| ---------------------- | ---------------------------------------------------------------------------------------- |
| `algonaut` | Top-level crate: the `atomic` group builder, `simulate`/`dryrun` helpers, and re-exports |
| `algonaut_algod` | Generated client for the algod v2 REST API |
| `algonaut_kmd` | Client for the key-management daemon |
| `algonaut_indexer` | Client for the indexer v2 REST API |
| `algonaut_core` | Core types: `Address`, `MicroAlgos`, `Round`, `AppId`/`AssetId`/`TransactionId`, keys, multisig |
| `algonaut_crypto` | Ed25519 sign/verify (via `ed25519-dalek`) and BIP-39 mnemonics |
| `algonaut_transaction` | Transaction builders and the open `Signer` trait |
| `algonaut_abi` | ARC-4 ABI types, method encoding, TEAL source-map decoder |
| `algonaut_abi_model` | Pure serde data model for ARC-4 / ARC-56 app-spec JSON, shared by the runtime and the macros |
| `algonaut_abi_sig` | ARC-4 signature/type grammar shared by the `contract!` macro and the runtime |
| `algonaut_abi_macros` | `contract!` proc-macro: typed ARC-4/ARC-56 contract client generator |
| `algonaut_encoding` | Shared `serde` visitors and base32/base64 helpers |
| `algonaut_model` | Hand-written response models shared between the clients |
## Running the examples
`/examples` has a wide set of runnable programs.
```bash
cp examples.env .env # ALGOD_URL, KMD_URL, INDEXER_URL, mnemonics
cargo run --example quickstart
```
If you see `Error: NotPresent`, your environment variables aren't set — `cp examples.env .env` and edit as needed.
## Changelog
See [CHANGELOG.md](./CHANGELOG.md).
## Contributing
Read the [contribution guidelines](./CONTRIBUTING.md) before opening a PR. The pre-commit hook runs `make ci`; commit messages follow [Conventional Commits](https://www.conventionalcommits.org/).
## Acknowledgements
This crate is based on the work of [@mraof](https://github.com/mraof/rust-algorand-sdk).
## License
[](https://crates.io/crates/algonaut)
Licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](./LICENSE-APACHE) or <https://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT](./LICENSE-MIT) or <https://opensource.org/licenses/MIT>)
at your option.
### Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.
### Asset attribution
[Ferris Algonaut](assets/ferris-algonaut.svg) is licensed under a [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).
[Rust `algonaut`'s logo](assets/rocket-solid.svg) is based on [Font Awesome](https://fontawesome.com/v5.15/icons/rocket)'s icon and licensed under a [Creative Commons Attribution 4.0 International License](https://creativecommons.org/licenses/by/4.0/).