iroh-topic-tracker 0.1.8

Iroh universal (gossipsub) topic tracker.
Documentation
# iroh-topic-tracker

[![Crates.io](https://img.shields.io/crates/v/iroh-topic-tracker.svg)](https://crates.io/crates/iroh-topic-tracker)
[![Docs.rs](https://docs.rs/iroh-topic-tracker/badge.svg)](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 iroh_topic_tracker::integrations::iroh_gossip::*;


#[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: Message))) = 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();
}
```

### Basic Setup with Iroh
```rust
use iroh::{protocol::Router, Endpoint};
use iroh_topic_tracker::topic_tracker::{ALPN, 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(ALPN, topic_tracker.clone())
        .spawn()
        .await?;

    // Track peers in a topic
    let topic = iroh_gossip::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 or
  <http://www.apache.org/licenses/LICENSE-2.0>)
- MIT license ([LICENSE-MIT]LICENSE-MIT 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.