use std::time::Duration;
use bingle_core::api::bingle_api::REFUSAL_UNAUTHENTICATED;
pub const DISCOVERY_WAIT: Duration = Duration::from_secs(30);
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelayRef {
pub id: String,
pub address: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RelayRefusal {
pub relay_id: String,
pub reason: String,
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RelayCheckPlan {
Probe(Vec<RelayRef>),
NoneDiscovered,
Refused(Vec<RelayRefusal>),
NoneAnswered(Vec<RelayRef>),
}
pub fn plan_relay_check(
listed: Vec<RelayRef>,
discovered: Vec<RelayRef>,
refusals: Vec<RelayRefusal>,
) -> RelayCheckPlan {
if !listed.is_empty() {
RelayCheckPlan::Probe(listed)
} else if !refusals.is_empty() {
RelayCheckPlan::Refused(refusals)
} else if discovered.is_empty() {
RelayCheckPlan::NoneDiscovered
} else {
RelayCheckPlan::NoneAnswered(discovered)
}
}
pub fn describe_plan(
plan: &RelayCheckPlan,
app_id: u64,
my_address: &str,
own_handle_registered: Option<bool>,
waited: Duration,
) -> Vec<String> {
match plan {
RelayCheckPlan::Probe(_) => Vec::new(),
RelayCheckPlan::NoneDiscovered => vec![format!(
"No relays discovered for app {app_id}: no account advertises a relay endpoint on chain"
)],
RelayCheckPlan::Refused(refusals) => {
let cause = match own_handle_registered {
Some(false) => format!(
"this account ({my_address}) has no handle on app {app_id}: register it \
(bingle_cli register) or, if it is registered on an earlier app, migrate it \
(bingle_cli migrate)"
),
Some(true) => format!(
"this account ({my_address}) has a handle on app {app_id}, so the relay could \
not read it from the chain; check the relay's Algorand node"
),
None => format!(
"either this account ({my_address}) has no handle on app {app_id} (register or \
migrate it), or the relay could not read the chain"
),
};
let mut lines = vec![format!("Relays refused this account: {cause}")];
for r in refusals {
if r.reason == REFUSAL_UNAUTHENTICATED {
lines.push(format!(
" relay {} could not authenticate this account",
r.relay_id
));
} else {
lines.push(format!(" relay {} refused: {}", r.relay_id, r.reason));
}
}
lines
}
RelayCheckPlan::NoneAnswered(discovered) => {
let mut lines = vec![format!(
"Found {} relay(s) for app {app_id} but none answered within {}s:",
discovered.len(),
waited.as_secs()
)];
for r in discovered {
lines.push(format!(" relay {} @ {}", r.id, r.address));
}
lines
}
}
}