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
//! Network-resilience helpers for on-chain reads and remote fetches.
//!
//! **Why this exists.** Every `registry::*` read goes through `reqwest`,
//! which on `wasm32` is a thin wrapper over the browser `fetch` API. The
//! browser gives `fetch` **no default timeout** and `reqwest::Client::timeout`
//! is a documented no-op on wasm — so a TCP-connected-but-silent RPC node (a
//! "black hole", common on flaky mobile networks or a stalled proxy) yields a
//! future that **never resolves**. Awaiting it directly hangs the calling
//! paint/refresh path forever, which on the UI looks like a permanent
//! `loading…` pill or a frozen verify state with no error.
//!
//! [`with_timeout`] caps any such future: it races the work against
//! [`crate::runtime::sleep_ms`] (a `setTimeout` Promise on wasm) and returns
//! `Err("timeout")` if the deadline wins. Callers then degrade to a usable
//! fallback (a dash, a hidden pill, the embedded docs) instead of spinning.
//!
//! This lives in `src/app/` rather than `registry.rs` deliberately — the
//! transport-level fix (a real fetch `AbortController`) is a follow-up for the
//! registry layer; until then the call sites that paint UI guard themselves.
use Future;
use ;
/// Default deadline for a single on-chain read used during a paint/refresh.
/// Long enough to absorb a slow-but-alive RPC round-trip, short enough that a
/// dead node degrades to a fallback within a couple seconds rather than
/// hanging the surface indefinitely.
pub const READ_TIMEOUT_MS: u32 = 8_000;
/// Race `fut` against a `ms`-millisecond timer. Returns `Ok(fut output)` if
/// the work finishes first, or `Err("timeout")` if the timer wins.
///
/// Pure combinator over [`crate::runtime::sleep_ms`] +
/// [`futures_util::future::select`] — no `tokio`, so it compiles + runs on wasm
/// (single-threaded, no `Send`). The losing future is simply dropped (browser
/// `fetch` is cancelled when its future drops).
pub async
/// Convenience wrapper at the [`READ_TIMEOUT_MS`] default — the common case for
/// an on-chain read feeding a paint.
pub async