# iroh-topic-tracker [](https://crates.io/crates/iroh-topic-tracker) [](https://docs.rs/iroh-topic-tracker) **A tracker for Iroh NodeId's in GossipSub topics.** This library integrates with [`iroh-gossip`](https://crates.io/crates/iroh-gossip) to automate peer discovery and includes a hosted `BOOTSTRAP_NODE` for seamless topic tracking without you needing to host anything. Your peers can discover each other even if both are behind NATs. --- ## Overview The crate provides a [`TopicTracker`](https://docs.rs/iroh-topic-tracker/latest/iroh_topic_tracker/topic_tracker/struct.TopicTracker.html) to manage and discover peers participating in shared GossipSub topics. It leverages Iroh's direct connectivity and [`Router`](https://docs.rs/iroh/latest/iroh/protocol/struct.Router.html) to handle protocol routing. ### Features - Automatic peer discovery via `iroh-gossip` (enabled with `iroh-gossip-auto-discovery` feature). - Dedicated bootstrap node support for topic tracking. - Simple API to fetch active peers for a topic. --- ## Getting Started ### Prerequisites Add the crate to your `Cargo.toml` with the required features: ```toml [dependencies] iroh-topic-tracker = { version = "0.1", features = ["iroh-gossip-auto-discovery"] } ``` ### Automatic Discovery Enable `iroh-gossip` integration to automate peer discovery for topics: ```rust use futures_lite::StreamExt; use iroh::Endpoint; use iroh_gossip::net::{Event, Gossip, GossipEvent}; use iroh_topic_tracker::{integrations::iroh_gossip::*, topic_tracker::Topic}; #[tokio::main] async fn main() -> anyhow::Result<()> { // Configure Iroh endpoint with discovery let endpoint = Endpoint::builder().discovery_n0().bind().await?; // Configure gossip protocol with auto-discovery let gossip = Gossip::builder() .spawn_with_auto_discovery(endpoint.clone()) .await?; // Join a topic and start tracking let topic = Topic::from_passphrase("my-iroh-gossip-topic"); let (sink, mut stream) = gossip.subscribe_and_join(topic.into()).await?.split(); // Read from stream .. while let Some(event) = stream.next().await { if let Ok(Event::Gossip(GossipEvent::Received(msg))) = event { // Do something with msg... let msg_text = String::from_utf8(msg.content.to_vec()).unwrap(); } } // .. or Send to Sink sink.broadcast("my msg goes here".into()).await.unwrap(); Ok(()) } ``` ### Basic Setup with Iroh ```rust use iroh::{protocol::Router, Endpoint}; use iroh_topic_tracker::topic_tracker::{Topic, TopicTracker}; #[tokio::main] async fn main() -> anyhow::Result<()> { // Configure Iroh endpoint with discovery let endpoint = Endpoint::builder().discovery_n0().bind().await?; // Initialize topic tracker let topic_tracker = TopicTracker::new(&endpoint); // Attach to Iroh router let router = Router::builder(endpoint.clone()) .accept(TopicTracker::ALPN, topic_tracker.clone()) .spawn() .await?; // Track peers in a topic let topic = Topic::from_passphrase("my-secret-topic"); let peers = topic_tracker.get_topic_nodes(&topic).await?; Ok(()) } ``` --- ## Examples ### Run a Topic Tracker Node Start a dedicated tracker node: ```bash cargo run --example server ``` *Note: Update `secret.rs` with your `SecretKey` and configure `BOOTSTRAP_NODES` in `topic_tracker.rs` for secure communication.* ### Query Active Peers Fetch the latest NodeIds for a topic: ```bash cargo run --example client ``` --- ## Building Optimized release build for the tracker server: ```bash cargo build --release --example server ``` --- ## License This project is licensed under either of - Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE.txt) or <http://www.apache.org/licenses/LICENSE-2.0>) - MIT license ([LICENSE-MIT](LICENSE-MIT.txt) or <http://opensource.org/licenses/MIT>) at your option. ### Contribution Unless explicitly stated, any contribution intentionally submitted for inclusion in this project shall be dual-licensed as above, without any additional terms or conditions.