xenith-core 0.1.0

Transport-agnostic traits, types, and errors for xenith cross-chain state sync
Documentation
# xenith

Cross-chain state sync for Rust — transport-agnostic, divergence-explicit, bot-first.

## The Problem

Multi-chain protocols share state across EVM networks using ad-hoc messaging (LayerZero,
CCIP, Axelar), but there is no standardized primitive that sits *above* those transports.
Every team ends up rewriting the same glue: serializing state updates into message payloads,
tracking in-flight message IDs, comparing observed values across chains, and deciding what
to do when two chains disagree. The absence of a shared abstraction means teams are locked
into a single messaging protocol from day one, and divergence bugs — where different chains
hold silently inconsistent state — are caught only when a liquidation misfires or an
arbitrage reverts.

## What xenith is

xenith is a transport-agnostic, Rust-native library that treats cross-chain state sync as a
first-class primitive. You plug in any messaging transport (`LayerZero`, `CCIP`, or your
own), and xenith handles local persistence, message dispatch, and read-back under a
`ReadStrategy` you choose. Diverged state is never silently resolved — `SyncStatus::Diverged`
surfaces to the caller who is always in control of conflict resolution. The `MultiChainReader`
issues parallel RPC reads across chains so keeper bots and arbitrage engines get consistent
snapshots without blocking on sequential calls.

## Quick Start

Add the crates you need to `Cargo.toml`:

```toml
[dependencies]
xenith-core      = "0.1"
xenith-layerzero = "0.1"
xenith-sync      = "0.1"
```

Push a state value from Ethereum to Arbitrum, then read it back:

```rust,ignore
use std::sync::Arc;
use bytes::Bytes;
use xenith_core::{ChainId, InMemoryStore, ReadStrategy, StateKey};
use xenith_layerzero::LayerZeroTransport;
use xenith_sync::{SyncConfig, SyncEngine};

#[tokio::main]
async fn main() -> xenith_core::Result<()> {
    // LayerZero endpoint IDs: Ethereum mainnet = 30101, Arbitrum = 30110
    let transport = Arc::new(LayerZeroTransport::new(
        [0u8; 20], // endpoint contract address on the source chain
        vec![
            (ChainId::from(1),     30101),
            (ChainId::from(42161), 30110),
        ],
    ));

    let engine = SyncEngine::new(
        transport,
        Arc::new(InMemoryStore::default()),
        SyncConfig::default(),
    );

    let key = StateKey::new("uniswap", "pool", "0xabc123");

    // Store locally and broadcast to Arbitrum.
    let receipt = engine
        .push(
            key.clone(),
            Bytes::from_static(b"price=3400"),
            vec![ChainId::from(42161)],
            ChainId::from(1), // source chain
            None,             // no on-chain metadata needed for this push
        )
        .await?;

    println!("dispatched to {} chain(s)", receipt.successes.len());

    // Read back; Ethereum is the declared source of truth.
    let state = engine
        .read(key, ReadStrategy::SourceOfTruth(ChainId::from(1)))
        .await?;

    println!("status: {:?}", state.status); // SyncStatus::Synced
    println!("data:   {:?}", state.value.data);

    Ok(())
}
```

## Crate Overview

| Crate | Description |
|---|---|
| [`xenith-core`]xenith-core/ | Transport-agnostic traits, domain newtypes, `XenithError`, `InMemoryStore`, and `ConflictResolver`. No external deps beyond `alloy-primitives`, `async-trait`, `thiserror`, and `bytes`. |
| [`xenith-layerzero`]xenith-layerzero/ | LayerZero v2 `MessagingTransport` implementation; stub behaviour by default, real endpoint calls behind the `live` feature flag. |
| [`xenith-sync`]xenith-sync/ | `SyncEngine` — the primary API surface. Composes a transport and a store to provide `push`, `read`, and `resolve`. |
| [`xenith-read`]xenith-read/ | `MultiChainReader` — issues parallel RPC reads across many chains simultaneously and reports storage-slot divergence. |

## Transport Support

| Transport | Status | Notes |
|---|---|---|
| [LayerZero v2]https://layerzero.network | **v0.1** | Stub impl ships now; `live` feature gates real endpoint calls |
| [Chainlink CCIP]https://chain.link/cross-chain | v0.2 planned | `xenith-ccip` crate |
| [Axelar]https://axelar.network | v0.3 planned | `xenith-axelar` crate |

## Contributing

PRs are welcome. Before submitting, run:

```bash
cargo clippy --workspace -- -D warnings
cargo fmt
cargo test --workspace
```

All three must pass clean. Clippy warnings are treated as errors; the formatter is
non-negotiable. If you are adding a new transport, implement the `transport_compliance_tests!`
macro suite from `xenith-core` to verify conformance.

**Stability:** xenith follows Semantic Versioning. While on 0.x.y, minor version bumps may
include breaking changes. Patch bumps are always backwards compatible. Subscribe to releases
on GitHub to be notified of breaking changes.

**Publishing:** Crates are published manually by the maintainer after each release tag. To
publish for the first time, the semver CI job must be initialized: tag a `v0.0.1` release
with the current codebase as the baseline before making any API changes.