1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#[cfg(test)]
mod test_client;
#[cfg(feature = "simulated-payouts")]
mod tokens;
use anyhow::{anyhow, Context, Result};
use dirs_next::home_dir;
use std::{collections::HashSet, fs::File, io::BufReader, net::SocketAddr};
#[cfg(test)]
pub use test_client::{create_test_client, create_test_client_with, init_logger};
#[cfg(feature = "simulated-payouts")]
pub use tokens::{calculate_new_balance, gen_ed_keypair};
const GENESIS_CONN_INFO_FILEPATH: &str = ".safe/node/node_connection_info.config";
pub fn read_network_conn_info() -> Result<HashSet<SocketAddr>> {
let user_dir = home_dir().ok_or_else(|| anyhow!("Could not fetch home directory"))?;
let conn_info_path = user_dir.join(GENESIS_CONN_INFO_FILEPATH);
let file = File::open(&conn_info_path).with_context(|| {
format!(
"Failed to open node connection information file at '{}'",
conn_info_path.display(),
)
})?;
let reader = BufReader::new(file);
let contacts: HashSet<SocketAddr> = serde_json::from_reader(reader).with_context(|| {
format!(
"Failed to parse content of node connection information file at '{}'",
conn_info_path.display(),
)
})?;
Ok(contacts)
}
#[cfg(test)]
#[macro_export]
macro_rules! retry_loop {
($async_func:expr) => {
loop {
match $async_func.await {
Ok(val) => break val,
Err(_) => tokio::time::sleep(std::time::Duration::from_millis(200)).await,
}
}
};
}
#[cfg(test)]
#[macro_export]
macro_rules! retry_loop_for_pattern {
($async_func:expr, $pattern:pat $(if $cond:expr)?) => {
loop {
let result = $async_func.await;
match &result {
$pattern $(if $cond)? => break result,
Ok(_) | Err(_) => tokio::time::sleep(std::time::Duration::from_millis(200)).await,
}
}
};
}