rename: sulkta-wallet → aldabra (per Cobb 2026-05-04)
Aldabra giant tortoise (Aldabrachelys gigantea) — endemic to the
Aldabra atoll, up to 250 kg, 150-year lifespan. Long-lived,
defended, slow but unstoppable. Better metaphor for the wallet
than 'sulkta-wallet' which was on-the-tin descriptive.
All renames in one pass:
- repo: Sulkta-Coop/sulkta-wallet → Sulkta-Coop/aldabra (via gitea API)
- workspace dir: sulkta-wallet → aldabra
- crate dirs: wallet-{core,chain,mcp} → aldabra-{core,chain,mcp}
- crate names + path imports in Cargo.toml workspace + each crate
- binary name: sulkta-wallet → aldabra
- README, ROADMAP, docs/architecture: all references swept
This commit is contained in:
parent
489b58cc1e
commit
1f1993ed97
10 changed files with 63 additions and 58 deletions
21
Cargo.toml
21
Cargo.toml
|
|
@ -1,9 +1,14 @@
|
|||
# Cargo workspace root for sulkta-wallet.
|
||||
# Cargo workspace root for aldabra.
|
||||
#
|
||||
# Three crates:
|
||||
# wallet-core — key derivation, signing, types, mnemonic handling
|
||||
# wallet-chain — pluggable chain backends (Koios, Ogmios). Trait-first.
|
||||
# wallet-mcp — binary; the MCP server, glues core+chain together.
|
||||
# aldabra-core — key derivation, signing, types, mnemonic handling
|
||||
# aldabra-chain — pluggable chain backends (Koios, Ogmios). Trait-first.
|
||||
# aldabra-mcp — binary; the MCP server, glues core+chain together.
|
||||
#
|
||||
# Named for the Aldabra giant tortoise (Aldabrachelys gigantea) — endemic
|
||||
# to the Aldabra atoll in the Seychelles, up to 250 kg, 150-year lifespan.
|
||||
# Long-lived, defended, slow but unstoppable. Fitting metaphor for a
|
||||
# wallet that holds your money.
|
||||
#
|
||||
# Workspace deps are pinned here so all three crates use the same versions.
|
||||
# Add a dep here, then reference it in each crate's Cargo.toml as
|
||||
|
|
@ -11,16 +16,16 @@
|
|||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"crates/wallet-core",
|
||||
"crates/wallet-chain",
|
||||
"crates/wallet-mcp",
|
||||
"crates/aldabra-core",
|
||||
"crates/aldabra-chain",
|
||||
"crates/aldabra-mcp",
|
||||
]
|
||||
|
||||
[workspace.package]
|
||||
version = "0.0.1"
|
||||
edition = "2021"
|
||||
license-file = "LICENSE"
|
||||
repository = "http://192.168.0.5:3001/Sulkta-Coop/sulkta-wallet"
|
||||
repository = "http://192.168.0.5:3001/Sulkta-Coop/aldabra"
|
||||
authors = ["Cobb <cobb@sulkta.com>", "Kayos <kayos@sulkta.com>"]
|
||||
|
||||
[workspace.dependencies]
|
||||
|
|
|
|||
22
README.md
22
README.md
|
|
@ -1,4 +1,4 @@
|
|||
# sulkta-wallet
|
||||
# aldabra
|
||||
|
||||
Rust-native Cardano lite wallet with an MCP-server interface — built
|
||||
for LLM-first usage (send, receive, mint, Plutus interaction).
|
||||
|
|
@ -25,20 +25,20 @@ Three crates in a Cargo workspace:
|
|||
|
||||
| Crate | Responsibility |
|
||||
|---|---|
|
||||
| `wallet-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. |
|
||||
| `wallet-chain` | Pluggable backends for chain queries. `ChainBackend` trait, with Koios as the phase-1 implementation. Ogmios + submission paths in phase 2. |
|
||||
| `wallet-mcp` | Binary. MCP server speaking stdio. Glues core + chain together, exposes tools to the LLM client. |
|
||||
| `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 │ wallet-mcp (bin) │ stdio
|
||||
LLM client │ aldabra-mcp (bin) │ stdio
|
||||
─────────► │ tool handlers, lifecycle │ ────►
|
||||
└──────────┬──────────────────┘
|
||||
│
|
||||
┌────────┴────────┐
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ wallet-core │ │ wallet-chain │
|
||||
│ aldabra-core │ │ aldabra-chain │
|
||||
│ keys, sign │ │ Koios/Ogmios │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
|
@ -70,21 +70,21 @@ Phase 4:
|
|||
cargo build --release
|
||||
|
||||
# Through crafting-table (preferred — validates the toolchain there)
|
||||
crafting-table build sulkta-wallet
|
||||
crafting-table build aldabra
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```bash
|
||||
# Direct invocation (smoke test only — does nothing useful in phase 1)
|
||||
./target/release/sulkta-wallet
|
||||
./target/release/aldabra
|
||||
|
||||
# As an MCP server registered with Claude Code:
|
||||
# add to ~/.claude.json:
|
||||
# "sulkta-wallet": {
|
||||
# "command": "/path/to/sulkta-wallet",
|
||||
# "aldabra": {
|
||||
# "command": "/path/to/aldabra",
|
||||
# "env": {
|
||||
# "SULKTA_WALLET_DATA": "/mnt/cache/appdata/sulkta-wallet"
|
||||
# "ALDABRA_DATA": "/mnt/cache/appdata/aldabra"
|
||||
# }
|
||||
# }
|
||||
```
|
||||
|
|
|
|||
16
ROADMAP.md
16
ROADMAP.md
|
|
@ -1,4 +1,4 @@
|
|||
# sulkta-wallet roadmap
|
||||
# aldabra roadmap
|
||||
|
||||
Phased buildout. Each phase ships a usable increment + leaves the
|
||||
codebase in a state where Phase N+1 picks up cleanly.
|
||||
|
|
@ -9,12 +9,12 @@ codebase in a state where Phase N+1 picks up cleanly.
|
|||
end-to-end through the MCP transport.
|
||||
|
||||
- [x] Cargo workspace
|
||||
- [x] Crate skeletons: `wallet-core`, `wallet-chain`, `wallet-mcp`
|
||||
- [x] Crate skeletons: `aldabra-core`, `aldabra-chain`, `aldabra-mcp`
|
||||
- [x] Type stubs + ZeroizeOnDrop scaffolding for keys
|
||||
- [ ] `wallet-core::Mnemonic::into_root_key` — real CIP-3 derivation via `pallas-crypto`
|
||||
- [ ] `wallet-core::derive_base_address` — real CIP-1852 + bech32
|
||||
- [ ] `wallet-chain::KoiosClient::get_utxos` — real `reqwest` to `/address_utxos`
|
||||
- [ ] `wallet-chain::KoiosClient::get_balance`
|
||||
- [ ] `aldabra-core::Mnemonic::into_root_key` — real CIP-3 derivation via `pallas-crypto`
|
||||
- [ ] `aldabra-core::derive_base_address` — real CIP-1852 + bech32
|
||||
- [ ] `aldabra-chain::KoiosClient::get_utxos` — real `reqwest` to `/address_utxos`
|
||||
- [ ] `aldabra-chain::KoiosClient::get_balance`
|
||||
- [ ] Interactive mnemonic bootstrap CLI: paste once, age-encrypt to disk
|
||||
- [ ] On-startup decryption — single passphrase prompt, derived key in
|
||||
RAM only
|
||||
|
|
@ -30,8 +30,8 @@ a Koios query.**
|
|||
|
||||
**Goal:** the wallet can spend.
|
||||
|
||||
- [ ] `wallet-chain::ChainBackend::submit_tx` — POST CBOR to Koios `/submittx`
|
||||
- [ ] `wallet-chain::tx_status` — poll `/tx_info`
|
||||
- [ ] `aldabra-chain::ChainBackend::submit_tx` — POST CBOR to Koios `/submittx`
|
||||
- [ ] `aldabra-chain::tx_status` — poll `/tx_info`
|
||||
- [ ] Build + sign ADA-only payment via `pallas-txbuilder`
|
||||
- [ ] MCP tool `wallet.send` with `to_address`, `lovelace` args
|
||||
- [ ] MCP tool `wallet.tx_status` with `tx_hash` arg
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
# wallet-chain — pluggable backends for chain queries.
|
||||
# aldabra-chain — pluggable backends for chain queries.
|
||||
#
|
||||
# A `ChainBackend` trait abstracts over Koios (HTTPS), Ogmios (WS/HTTP),
|
||||
# or any future option. Phase 1 ships with a Koios implementation since
|
||||
|
|
@ -7,7 +7,7 @@
|
|||
# Submission paths land in phase 2. Read-only queries first.
|
||||
|
||||
[package]
|
||||
name = "wallet-chain"
|
||||
name = "aldabra-chain"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license-file.workspace = true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! sulkta-wallet chain backends — Koios first, Ogmios next.
|
||||
//! aldabra chain backends — Koios first, Ogmios next.
|
||||
//!
|
||||
//! Trait-first design: the MCP server depends on `ChainBackend`, not on
|
||||
//! a specific implementation. Swapping Koios → Ogmios is a config change.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# wallet-core — pure crypto + types. No I/O, no network. Deterministic
|
||||
# aldabra-core — pure crypto + types. No I/O, no network. Deterministic
|
||||
# given the same mnemonic + derivation path.
|
||||
#
|
||||
# This crate is intentionally narrow:
|
||||
|
|
@ -6,18 +6,18 @@
|
|||
# - Root key → payment / stake key (CIP-1852 derivation)
|
||||
# - Address construction (mainnet, testnet)
|
||||
# - Transaction signing (given an unsigned TX builder output from
|
||||
# wallet-chain or pallas-txbuilder)
|
||||
# aldabra-chain or pallas-txbuilder)
|
||||
#
|
||||
# It deliberately does NOT:
|
||||
# - Do any chain queries (that's wallet-chain's job)
|
||||
# - Talk to MCP (that's wallet-mcp's job)
|
||||
# - Do any chain queries (that's aldabra-chain's job)
|
||||
# - Talk to MCP (that's aldabra-mcp's job)
|
||||
# - Touch files (the daemon owns disk I/O; we get keys handed in)
|
||||
#
|
||||
# Rationale: this is the most security-sensitive crate. Keeping it
|
||||
# narrow + I/O-free makes it auditable.
|
||||
|
||||
[package]
|
||||
name = "wallet-core"
|
||||
name = "aldabra-core"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license-file.workspace = true
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! sulkta-wallet core — keys, addresses, signing.
|
||||
//! aldabra core — keys, addresses, signing.
|
||||
//!
|
||||
//! This crate is the security boundary. Everything that touches private
|
||||
//! key material lives here, and only here. No I/O, no network, no MCP.
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# wallet-mcp — the binary. MCP server speaking stdio that exposes
|
||||
# aldabra-mcp — the binary. MCP server speaking stdio that exposes
|
||||
# the wallet's tools to an LLM. Spawned as a subprocess from any MCP
|
||||
# client (Claude Code, OpenClaw, etc.).
|
||||
#
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
# between core + chain crates.
|
||||
|
||||
[package]
|
||||
name = "wallet-mcp"
|
||||
name = "aldabra-mcp"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license-file.workspace = true
|
||||
|
|
@ -14,12 +14,12 @@ repository.workspace = true
|
|||
authors.workspace = true
|
||||
|
||||
[[bin]]
|
||||
name = "sulkta-wallet"
|
||||
name = "aldabra"
|
||||
path = "src/main.rs"
|
||||
|
||||
[dependencies]
|
||||
wallet-core = { path = "../wallet-core" }
|
||||
wallet-chain = { path = "../wallet-chain" }
|
||||
aldabra-core = { path = "../aldabra-core" }
|
||||
aldabra-chain = { path = "../aldabra-chain" }
|
||||
|
||||
tokio = { workspace = true }
|
||||
anyhow = { workspace = true }
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
//! sulkta-wallet — MCP server entry point.
|
||||
//! aldabra — MCP server entry point.
|
||||
//!
|
||||
//! Speaks MCP over stdio. Any MCP client (Claude Code, OpenClaw, etc.)
|
||||
//! launches this as a subprocess and gets a wallet's worth of tools.
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
//! ## Phase 1 tools
|
||||
//!
|
||||
//! - `wallet.address` — return the derived base address (placeholder
|
||||
//! until wallet-core's CIP-1852 derivation lands)
|
||||
//! until aldabra-core's CIP-1852 derivation lands)
|
||||
//! - `wallet.balance` — query balance via the configured chain backend
|
||||
//!
|
||||
//! ## Phase 2-4 tools (TODO)
|
||||
|
|
@ -34,7 +34,7 @@ async fn main() -> Result<()> {
|
|||
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or_else(|_| "info".into()))
|
||||
.init();
|
||||
|
||||
tracing::info!("sulkta-wallet starting (phase 1 scaffold)");
|
||||
tracing::info!("aldabra starting (phase 1 scaffold)");
|
||||
|
||||
// TODO(phase 1):
|
||||
// 1. Load config (network, koios url, mnemonic path)
|
||||
|
|
@ -47,9 +47,9 @@ async fn main() -> Result<()> {
|
|||
// For now: a smoke-test print so the binary actually does something
|
||||
// when invoked manually (not through MCP).
|
||||
tracing::info!(
|
||||
target_address = %wallet_core::derive_base_address(
|
||||
target_address = %aldabra_core::derive_base_address(
|
||||
&dummy_root_key()?,
|
||||
wallet_core::Network::Mainnet,
|
||||
aldabra_core::Network::Mainnet,
|
||||
0,
|
||||
0,
|
||||
)?,
|
||||
|
|
@ -62,13 +62,13 @@ async fn main() -> Result<()> {
|
|||
/// Phase 1 only — produces a zero-bytes RootKey so the placeholder
|
||||
/// address derivation runs. Will be deleted once real mnemonic loading
|
||||
/// lands.
|
||||
fn dummy_root_key() -> Result<wallet_core::RootKey> {
|
||||
fn dummy_root_key() -> Result<aldabra_core::RootKey> {
|
||||
// Need a way to construct one from this crate without exposing
|
||||
// private fields. Phase 1: temporary public constructor on
|
||||
// wallet-core, gated behind a #[cfg(test)] or feature flag and
|
||||
// aldabra-core, gated behind a #[cfg(test)] or feature flag and
|
||||
// removed before phase 2.
|
||||
//
|
||||
// For tonight: this fn is a TODO marker — the smoke test won't
|
||||
// actually run until we finish wallet-core::Mnemonic::into_root_key.
|
||||
// actually run until we finish aldabra-core::Mnemonic::into_root_key.
|
||||
anyhow::bail!("phase 1 scaffold: real mnemonic loading not yet implemented")
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
# sulkta-wallet architecture notes
|
||||
# aldabra architecture notes
|
||||
|
||||
Deeper design notes than the README. Read this before extending.
|
||||
|
||||
|
|
@ -7,15 +7,15 @@ Deeper design notes than the README. Read this before extending.
|
|||
The three-crate split exists to keep the security-sensitive code
|
||||
auditable in isolation.
|
||||
|
||||
- `wallet-core` — **no I/O.** Given a mnemonic + a derivation path,
|
||||
- `aldabra-core` — **no I/O.** Given a mnemonic + a derivation path,
|
||||
produces keys + addresses + signatures. Deterministic, no
|
||||
dependencies on tokio, reqwest, MCP, or anything that could
|
||||
introduce side channels. Easy to audit because it's narrow.
|
||||
- `wallet-chain` — **all the I/O lives here.** Trait-first so the MCP
|
||||
- `aldabra-chain` — **all the I/O lives here.** Trait-first so the MCP
|
||||
layer never knows whether it's talking to Koios, Ogmios, or a future
|
||||
backend. Future contributors swap implementations without touching
|
||||
the security-sensitive crate.
|
||||
- `wallet-mcp` — **the binary glue.** Owns process lifecycle, config
|
||||
- `aldabra-mcp` — **the binary glue.** Owns process lifecycle, config
|
||||
loading, MCP transport, tool registration, error mapping. The
|
||||
thinnest layer.
|
||||
|
||||
|
|
@ -36,7 +36,7 @@ roughly in order:
|
|||
`--dry-run` flag for any state-changing tool.
|
||||
2. **Daemon process compromise.** If the wallet binary is exploited
|
||||
(e.g. via a malformed Koios response triggering memory corruption),
|
||||
the keys are at risk. Mitigations: keep `wallet-core` narrow
|
||||
the keys are at risk. Mitigations: keep `aldabra-core` narrow
|
||||
(smaller attack surface), zeroize on drop, future: drop
|
||||
privileges + seccomp the daemon.
|
||||
3. **Disk read.** The encrypted mnemonic on disk could be exfiltrated.
|
||||
|
|
@ -56,18 +56,18 @@ roughly in order:
|
|||
First run:
|
||||
user pastes mnemonic at interactive prompt
|
||||
↓
|
||||
wallet-mcp asks for an encryption passphrase
|
||||
aldabra-mcp asks for an encryption passphrase
|
||||
↓
|
||||
age-encrypt the mnemonic phrase
|
||||
↓
|
||||
write to $SULKTA_WALLET_DATA/mnemonic.age
|
||||
write to $ALDABRA_DATA/mnemonic.age
|
||||
↓
|
||||
derive RootKey, hold in RAM, zeroize the source phrase
|
||||
↓
|
||||
daemon ready
|
||||
|
||||
Subsequent runs:
|
||||
read $SULKTA_WALLET_DATA/mnemonic.age
|
||||
read $ALDABRA_DATA/mnemonic.age
|
||||
↓
|
||||
prompt for passphrase
|
||||
↓
|
||||
|
|
@ -114,7 +114,7 @@ phase-2 design is:
|
|||
2. Returns the unsigned CBOR + a one-line human summary ("send 100
|
||||
ADA to addr1xyz, fee 0.17 ADA, expected balance after: …").
|
||||
3. LLM relays the summary to Cobb, gets approval.
|
||||
4. Cobb runs a separate `sulkta-wallet-cold-sign` CLI on a different
|
||||
4. Cobb runs a separate `aldabra-cold-sign` CLI on a different
|
||||
box (offline laptop, cardano-signer, whatever) — paste the CBOR,
|
||||
approve, paste back the signed CBOR.
|
||||
5. `wallet.submit_signed_tx` takes the signed CBOR + submits.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue