| Crates.io | xaeroflux |
| lib.rs | xaeroflux |
| version | 1.0.0 |
| created_at | 2025-04-11 19:36:11.465733+00 |
| updated_at | 2025-11-24 02:28:51.308991+00 |
| description | a decentralized, p2p, offline first event log built on tokio, rusqlite and iroh |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1630251 |
| size | 183,916 |
A decentralized peer-to-peer event log that syncs across devices using Iroh and SQLite.
[dependencies]
xaeroflux = { git = "https://github.com/block-xaero/xaeroflux" }
tokio = { version = "1", features = ["full"] }
use xaeroflux::{XaeroFlux, Event, generate_event_id};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut xf = XaeroFlux::new(
"my-app-key".to_string(),
"events.db".to_string()
).await?;
// Send an event
let now = chrono::Utc::now().timestamp() as u64;
xf.event_tx.send(Event {
id: generate_event_id("hello world", &xf.node_id, now),
payload: "hello world".to_string(),
source: xf.node_id.clone(),
ts: now,
})?;
// Receive synced events from other peers
while let Some(event) = xf.event_rx.recv().await {
println!("Received: {} from {}", event.payload, event.source);
}
Ok(())
}
pub struct Event {
pub id: String, // Unique ID (blake3 hash)
pub payload: String, // Your data (any string)
pub source: String, // Node ID that created event
pub ts: u64, // Unix timestamp
}
event_txxsp-1.0/{discovery_key}/eventsevent_rxEvents from your own node are not sent back to event_rx (you already have them).
The discovery key determines which peers sync with each other:
// These sync together (same discovery key)
let peer1 = XaeroFlux::new("project-alpha".to_string(), "db1.db".to_string()).await?;
let peer2 = XaeroFlux::new("project-alpha".to_string(), "db2.db".to_string()).await?;
// This syncs separately (different discovery key)
let peer3 = XaeroFlux::new("project-beta".to_string(), "db3.db".to_string()).await?;
cargo build --release --bin xaeroflux-cli
./target/release/xaeroflux-cli \
--discovery-key demo \
--db peer1.db \
send "Hello from peer 1"
./target/release/xaeroflux-cli \
--discovery-key demo \
--db peer2.db \
recv
The receiver will print events sent by the first peer (and any other peers on the same discovery key).
# Terminal 1
./target/release/xaeroflux-cli -k demo -d peer1.db send "Event 1"
./target/release/xaeroflux-cli -k demo -d peer1.db send "Event 2"
./target/release/xaeroflux-cli -k demo -d peer1.db send "Event 3"
./target/release/xaeroflux-cli -k demo -d peer1.db interactive
Type messages and press Enter. Type quit to exit.
use xaeroflux::{XaeroFlux, Event, generate_event_id};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
struct ChatMessage {
user: String,
message: String,
}
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut xf = XaeroFlux::new("my-chat".to_string(), "chat.db".to_string()).await?;
let node_id = xf.node_id.clone();
// Send chat messages
let tx = xf.event_tx.clone();
tokio::spawn(async move {
let stdin = tokio::io::stdin();
let mut lines = tokio::io::BufReader::new(stdin).lines();
while let Ok(Some(line)) = lines.next_line().await {
let msg = ChatMessage {
user: node_id[..8].to_string(),
message: line,
};
let payload = serde_json::to_string(&msg).unwrap();
let now = chrono::Utc::now().timestamp() as u64;
tx.send(Event {
id: generate_event_id(&payload, &node_id, now),
payload,
source: node_id.clone(),
ts: now,
}).unwrap();
}
});
// Receive and display messages
while let Some(event) = xf.event_rx.recv().await {
let msg: ChatMessage = serde_json::from_str(&event.payload)?;
println!("[{}] {}", msg.user, msg.message);
}
Ok(())
}
Topic: xsp-1.0/{discovery_key}/events
Transport: Iroh gossip
Format: JSON-serialized Event struct
MPL v2.0