rename: aldabra → aldabra (per Sulkta 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 'aldabra' which was on-the-tin descriptive.

All renames in one pass:
- repo: Sulkta-Coop/aldabra → Sulkta-Coop/aldabra (via gitea API)
- workspace dir: aldabra → aldabra
- crate dirs: wallet-{core,chain,mcp} → aldabra-{core,chain,mcp}
- crate names + path imports in Cargo.toml workspace + each crate
- binary name: aldabra → aldabra
- README, ROADMAP, docs/architecture: all references swept
This commit is contained in:
Sulkta 2026-05-04 10:11:23 -07:00
parent 56bcceb593
commit edc976e5d9
9 changed files with 39 additions and 34 deletions

View file

@ -0,0 +1,97 @@
//! 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.
//!
//! ## Phase 1
//! Just the trait + a stub `KoiosClient` that returns hardcoded data.
//! Real HTTP wired up next pass.
use serde::{Deserialize, Serialize};
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ChainError {
#[error("network error: {0}")]
Network(String),
#[error("backend returned malformed response: {0}")]
Decode(String),
#[error("not yet implemented (phase 1 scaffold)")]
NotYetImplemented,
}
/// One UTXO at an address. Multi-asset bundle is a flat map of
/// {policy_id+asset_name → quantity} for now; we'll model it more
/// strictly when minting lands in phase 3.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Utxo {
pub tx_hash: String,
pub output_index: u32,
pub lovelace: u64,
/// Hex-encoded `policy_id || asset_name_hex` → quantity.
/// Empty for plain ADA UTXOs.
pub assets: std::collections::BTreeMap<String, u64>,
}
/// Aggregated balance at an address.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Balance {
pub lovelace: u64,
pub assets: std::collections::BTreeMap<String, u64>,
}
#[async_trait::async_trait]
pub trait ChainBackend: Send + Sync {
async fn get_utxos(&self, address: &str) -> Result<Vec<Utxo>, ChainError>;
async fn get_balance(&self, address: &str) -> Result<Balance, ChainError>;
// Phase 2:
// async fn submit_tx(&self, raw_tx_cbor: &[u8]) -> Result<String, ChainError>;
// async fn tx_status(&self, tx_hash: &str) -> Result<TxStatus, ChainError>;
}
/// Stub Koios client. Phase 1: returns deterministic placeholder data
/// so the MCP server can be smoke-tested end-to-end without a chain
/// dependency. Phase 2: real reqwest calls to a Koios endpoint.
pub struct KoiosClient {
/// Base URL — typically https://api.koios.rest/api/v1
/// or your own self-hosted Koios deployment.
pub base_url: String,
}
impl KoiosClient {
pub fn new(base_url: impl Into<String>) -> Self {
Self {
base_url: base_url.into(),
}
}
}
#[async_trait::async_trait]
impl ChainBackend for KoiosClient {
async fn get_utxos(&self, _address: &str) -> Result<Vec<Utxo>, ChainError> {
// TODO(phase 1): POST /address_utxos with {"_addresses": [<address>]}
Ok(vec![])
}
async fn get_balance(&self, _address: &str) -> Result<Balance, ChainError> {
// TODO(phase 1): POST /address_info, sum balances across UTXOs
Ok(Balance {
lovelace: 0,
assets: Default::default(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn stub_koios_returns_empty() {
let client = KoiosClient::new("https://api.koios.rest/api/v1");
let bal = client.get_balance("addr1...").await.unwrap();
assert_eq!(bal.lovelace, 0);
}
}