Surfaced by Track #38 code audit (2026-05-09): 1. cargo fmt --all: 217 formatting diffs across 35 files. Pure whitespace; no semantic changes. 2. cargo clippy --fix: 30 warnings -> 10. Auto-applied: - useless format!() (3 sites in builder/proposal_*.rs) - needless_borrow_for_generic_args (4 sites) - cloned_ref_to_slice_refs (1 site, builder/proposal_cosign.rs) - derivable_impls (1 site, dao/config.rs) - unused imports/variables (3 sites) Remaining 10 warnings are non-trivial (too_many_arguments on a constructor at 8 args, FromStr trait shadow, doc_lazy_continuation on a few comment blocks). Filed as tech-debt; no action this pass. 3. cargo audit: 0 vulnerabilities. 2 unmaintained advisories on transitive deps: - paste 1.0.15 (RUSTSEC-2024-0436) via rmcp + pallas-traverse - proc-macro-error 1.0.4 (RUSTSEC-2024-0370) via age->i18n-embed-fl Both upstream; tracked but no action needed locally. 4. Test failure surfaced: builder::proposal_retract_votes::tests:: voting_ready_in_window_subtracts_vote_weight failed — cooldown check was applied unconditionally for RemoveVoterLockOnly mode, blocking the legitimate 'retract during voting window' path where the proposal datum mutates (vote weight subtraction). Per Agora's premoveLocks rule, cooldown only applies when retracting AFTER voting closed but BEFORE Finished — not during the active voting window. Fixed by gating cooldown on '!proposal_datum_will_change' so the in-window retract path bypasses cooldown the same way RemoveAllLocks does. Test: 87/87 aldabra-dao lib tests pass post-fix (was 86/87). |
||
|---|---|---|
| .cargo | ||
| crates | ||
| docs | ||
| .dockerignore | ||
| .gitignore | ||
| Cargo.lock | ||
| Cargo.toml | ||
| Dockerfile | ||
| LICENSE | ||
| README.md | ||
| ROADMAP.md | ||
aldabra
Rust-native Cardano lite wallet with an MCP-server interface — built for LLM-first usage (send, receive, mint, Plutus interaction).
Status: Phase 1 scaffold (2026-05-04). Compiles, structure in place, real wallet primitives still landing. See
ROADMAP.md.
Why
The existing Cardano MCP servers are either read-only doc gateways (Jimmyh-world/Cardano_MCP) or built on Blockfrost (web3-mcp) which is a centralized API we deliberately don't depend on. Sulkta runs its own Koios + Ogmios endpoints on Rackham; we want a wallet that talks directly to those.
Also: it's the first Sulkta Rust project — useful as a workout for
crafting-table's Rust toolchain (per Sulkta-Coop/lucy-infra
spec-crafting-table.md).
Architecture
Three crates in a Cargo workspace:
| Crate | Responsibility |
|---|---|
aldabra-core |
Pure crypto + types. Mnemonic → root key (CIP-3), root → payment + stake key (CIP-1852), address construction, signing. No I/O, no network. This is the security boundary. |
aldabra-chain |
Pluggable backends for chain queries. ChainBackend trait, with Koios as the phase-1 implementation. Ogmios + submission paths in phase 2. |
aldabra-mcp |
Binary. MCP server speaking stdio. Glues core + chain together, exposes tools to the LLM client. |
┌─────────────────────────────┐
LLM client │ aldabra-mcp (bin) │ stdio
─────────► │ tool handlers, lifecycle │ ────►
└──────────┬──────────────────┘
│
┌────────┴────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ aldabra-core │ │ aldabra-chain │
│ keys, sign │ │ Koios/Ogmios │
└──────────────┘ └──────────────┘
MCP tools (target)
Phase 1:
wallet.address— derived base address at account 0, index 0wallet.balance— ADA + native asset balance at the wallet's addresswallet.utxos— list UTXOs
Phase 2:
wallet.send— build, sign, submit a payment (ADA or native)wallet.tx_status— poll a submitted tx hash
Phase 3:
wallet.mint— mint a CIP-25 / CIP-68 native assetwallet.policy.create— generate a policy script (timelock, multisig)
Phase 4:
wallet.script.attach— attach an inline datum + reference scriptwallet.script.spend— spend a Plutus-locked UTXO with redeemerwallet.stake.delegate— delegate to a pool
Build
# Local (requires rustc 1.75+)
cargo build --release
# Through crafting-table (preferred — validates the toolchain there)
crafting-table build aldabra
Run
# Direct invocation (smoke test only — does nothing useful in phase 1)
./target/release/aldabra
# As an MCP server registered with Claude Code:
# add to ~/.claude.json:
# "aldabra": {
# "command": "/path/to/aldabra",
# "env": {
# "ALDABRA_DATA": "/mnt/cache/appdata/aldabra"
# }
# }
Security model
- Mnemonic source: interactive bootstrap on first run, paste once, encrypted at rest with age. Never written to disk in plaintext.
- Derived keys: in-memory only,
ZeroizeOnDropon every container. - Network exposure: stdio MCP transport — never opens a TCP socket. Only the spawning client process can reach it.
- Multi-network: mainnet by default, but
--network preview/--network preprodfor testing without real ADA.
See also
ROADMAP.md— phased buildoutdocs/architecture.md— deeper design notes- txpipe/pallas — the Rust Cardano building blocks we depend on
- Emurgo/cardano-serialization-lib — reference TX builder if pallas-txbuilder doesn't cover something
- modelcontextprotocol/rust-sdk — rmcp, the Rust MCP server SDK we use