Distributed Erlang over iroh P2P + TLS, with a bot powers SDK
1//! Peer bot that dials another bot over iroh and runs a few power demos.
2//!
3//! ```bash
4//! # terminal 1
5//! cargo run --example bot -- --name alpha
6//! # copy the endpoint id printed
7//!
8//! # terminal 2
9//! cargo run --example peer -- --name beta --peer <endpoint-id>
10//! ```
11
12use clap::Parser;
13use erl_iroh::bot::Bot;
14use erl_iroh::powers::Powers;
15use erl_iroh::term;
16use tracing_subscriber::EnvFilter;
17
18#[derive(Parser, Debug)]
19#[command(name = "peer", about = "dial an erl-iroh bot and exercise powers")]
20struct Args {
21 #[arg(long, default_value = "beta")]
22 name: String,
23
24 #[arg(long, default_value = "erl-iroh-cookie")]
25 cookie: String,
26
27 /// Remote iroh endpoint id.
28 #[arg(long)]
29 peer: String,
30}
31
32#[tokio::main]
33async fn main() -> erl_iroh::Result<()> {
34 tracing_subscriber::fmt()
35 .with_env_filter(EnvFilter::from_default_env().add_directive("erl_iroh=info".parse().unwrap()))
36 .init();
37
38 let args = Args::parse();
39
40 let bot = Bot::builder(args.name)
41 .cookie(args.cookie)
42 .powers(Powers::all())
43 .build()
44 .await?;
45
46 println!("local endpoint: {}", bot.endpoint_id());
47 println!("dialing {} …", args.peer);
48
49 let handle = bot.connect_iroh(&args.peer).await?;
50 println!("connected to erlang node {}", handle.peer_name());
51
52 // Both sides are Rust "fake" nodes — RPC to erpc only works against real BEAM.
53 // Still demonstrate SEND power with a registered-name message.
54 bot.send(
55 &handle.peer_name().to_string(),
56 "net_kernel",
57 term::atom("hello_from_peer").into(),
58 )
59 .await
60 .map_err(|e| {
61 eprintln!("send (best-effort): {e}");
62 e
63 })
64 .ok();
65
66 println!("peers: {:?}", bot.peers().await);
67 println!("done");
68 Ok(())
69}