1#![doc = include_str!("../README.md")]
2#![deny(missing_docs)]
5#![deny(rustdoc::broken_intra_doc_links)]
6#![cfg_attr(any(), deny(clippy::unwrap_used))]
7
8use std::time::Duration;
9
10use anyhow::Result;
11use http_relay::HttpRelay;
12use pubky::{ClientBuilder, Keypair};
13use pubky_common::timestamp::Timestamp;
14use pubky_homeserver::Homeserver;
15use url::Url;
16
17pub struct Testnet {
19 dht: mainline::Testnet,
20 relays: Vec<pkarr_relay::Relay>,
21}
22
23impl Testnet {
24 pub async fn run() -> Result<Self> {
26 let dht = mainline::Testnet::new(3)?;
27
28 let mut testnet = Self {
29 dht,
30 relays: vec![],
31 };
32
33 testnet.run_pkarr_relay().await?;
34
35 Ok(testnet)
36 }
37
38 pub async fn run_with_hardcoded_configurations() -> Result<Self> {
45 let dht = mainline::Testnet::new(3)?;
46
47 dht.leak();
48
49 let storage = std::env::temp_dir().join(Timestamp::now().to_string());
50
51 let mut builder = pkarr_relay::Relay::builder();
52 builder
53 .http_port(15411)
54 .storage(storage.clone())
55 .disable_rate_limiter()
56 .pkarr(|pkarr| {
57 pkarr
58 .request_timeout(Duration::from_millis(100))
59 .bootstrap(&dht.bootstrap)
60 .dht(|builder| {
61 if !dht.bootstrap.first().unwrap().contains("6881") {
62 builder.server_mode().port(6881);
63 }
64
65 builder
66 .bootstrap(&dht.bootstrap)
67 .request_timeout(Duration::from_millis(200))
68 })
69 });
70 let relay = unsafe { builder.run() }.await?;
71
72 let mut builder = Homeserver::builder();
73 builder
74 .keypair(Keypair::from_secret_key(&[0; 32]))
75 .storage(storage)
76 .bootstrap(&dht.bootstrap)
77 .relays(&[relay.local_url()])
78 .domain("localhost")
79 .close_signups()
80 .admin_password("admin".to_string());
81 unsafe { builder.run().await }?;
82
83 HttpRelay::builder().http_port(15412).run().await?;
84
85 let testnet = Self {
86 dht,
87 relays: vec![relay],
88 };
89
90 Ok(testnet)
91 }
92
93 pub fn bootstrap(&self) -> &[String] {
97 &self.dht.bootstrap
98 }
99
100 pub fn relays(&self) -> Box<[Url]> {
102 self.relays.iter().map(|r| r.local_url()).collect()
103 }
104
105 pub async fn run_homeserver(&self) -> Result<Homeserver> {
109 Homeserver::run_test(&self.dht.bootstrap).await
110 }
111
112 pub async fn run_homeserver_with_signup_tokens(&self) -> Result<Homeserver> {
114 Homeserver::run_test_with_signup_tokens(&self.dht.bootstrap).await
115 }
116
117 pub async fn run_http_relay(&self) -> Result<HttpRelay> {
119 HttpRelay::builder().run().await
120 }
121
122 pub fn client_builder(&self) -> ClientBuilder {
124 let bootstrap = self.bootstrap();
125 let relays = self.relays();
126
127 let mut builder = pubky::Client::builder();
128 builder.pkarr(|builder| {
129 builder
130 .bootstrap(bootstrap)
131 .relays(&relays)
132 .expect("testnet relays should be valid urls")
133 });
134
135 builder
136 }
137
138 pub async fn run_pkarr_relay(&mut self) -> Result<Url> {
142 let relay = pkarr_relay::Relay::run_test(&self.dht).await?;
143
144 let url = relay.local_url();
145
146 self.relays.push(relay);
147
148 Ok(url)
149 }
150}