@@ -310,6 +310,10 @@ pub struct PeerStatus {
310310 pub online : bool ,
311311 pub connectivity : PeerConnectivity ,
312312 pub url : String ,
313+ /// Guardian's reported `fedimintd` version. Travels with the peer status so
314+ /// the UI reflects guardian upgrades in real time (a guardian upgrade
315+ /// restarts fedimintd, which surfaces as a reconnect on the status stream).
316+ pub version : Option < String > ,
313317}
314318
315319#[ derive( Debug , Serialize , Clone ) ]
@@ -1510,19 +1514,17 @@ impl Multimint {
15101514 futures_util:: future:: join_all ( peers. iter ( ) . map ( |( peer_id, ( name, url) ) | {
15111515 let client = client. clone ( ) ;
15121516 async move {
1513- let online = client
1514- . api ( )
1515- . fedimintd_version ( ( * peer_id) . into ( ) )
1516- . await
1517- . is_ok ( ) ;
1517+ let fetched_version =
1518+ client. api ( ) . fedimintd_version ( ( * peer_id) . into ( ) ) . await . ok ( ) ;
15181519 PeerStatus {
15191520 peer_id : * peer_id,
15201521 name : name. clone ( ) ,
1521- online,
1522+ online : fetched_version . is_some ( ) ,
15221523 // The preview path calls fedimintd_version directly rather than
15231524 // going through the pooled connection, so the hop is always direct.
15241525 connectivity : PeerConnectivity :: Direct ,
15251526 url : url. clone ( ) ,
1527+ version : fetched_version,
15261528 }
15271529 }
15281530 } ) )
@@ -1534,28 +1536,67 @@ impl Multimint {
15341536 // Get the connection status stream from the client
15351537 let status_stream = client. api ( ) . connection_status_stream ( ) ;
15361538
1537- let mapped_stream = status_stream. map ( move |status_map| {
1538- let peers_status: Vec < PeerStatus > = peers
1539- . iter ( )
1540- . map ( |( peer_id, ( name, url) ) | {
1539+ // Fold the guardian version into each peer status so the UI reflects
1540+ // upgrades in real time without a separate timer. The version only needs
1541+ // (re)fetching when a peer comes online: a guardian upgrade restarts
1542+ // fedimintd, which surfaces here as an offline->online transition. We
1543+ // cache the last-known version per peer and refetch only on that
1544+ // transition (or if we never managed to fetch it) to avoid hitting every
1545+ // guardian on each unrelated connectivity change.
1546+ let mapped_stream = stream:: unfold (
1547+ (
1548+ Box :: pin ( status_stream) ,
1549+ client,
1550+ peers,
1551+ BTreeMap :: < u16 , Option < String > > :: new ( ) ,
1552+ BTreeMap :: < u16 , bool > :: new ( ) ,
1553+ ) ,
1554+ |( mut status_stream, client, peers, mut cached_versions, mut prev_online) | async move {
1555+ let status_map = status_stream. next ( ) . await ?;
1556+
1557+ let mut peers_status = Vec :: with_capacity ( peers. len ( ) ) ;
1558+ for ( peer_id, ( name, url) ) in peers. iter ( ) {
15411559 let ( online, connectivity) = match status_map. get ( & ( * peer_id) . into ( ) ) {
15421560 Some ( FedimintPeerStatus :: Connected ( c) ) => ( true , ( * c) . into ( ) ) ,
15431561 Some ( FedimintPeerStatus :: Disconnected ) | None => {
15441562 ( false , PeerConnectivity :: Unknown )
15451563 }
15461564 } ;
1547- PeerStatus {
1565+
1566+ let version = if online {
1567+ let was_online = prev_online. get ( peer_id) . copied ( ) . unwrap_or ( false ) ;
1568+ let have_version =
1569+ cached_versions. get ( peer_id) . is_some_and ( |v| v. is_some ( ) ) ;
1570+ if was_online && have_version {
1571+ cached_versions. get ( peer_id) . cloned ( ) . flatten ( )
1572+ } else {
1573+ let fetched =
1574+ client. api ( ) . fedimintd_version ( ( * peer_id) . into ( ) ) . await . ok ( ) ;
1575+ cached_versions. insert ( * peer_id, fetched. clone ( ) ) ;
1576+ fetched
1577+ }
1578+ } else {
1579+ None
1580+ } ;
1581+
1582+ prev_online. insert ( * peer_id, online) ;
1583+
1584+ peers_status. push ( PeerStatus {
15481585 peer_id : * peer_id,
15491586 name : name. clone ( ) ,
15501587 online,
15511588 connectivity,
15521589 url : url. clone ( ) ,
1553- }
1554- } )
1555- . collect ( ) ;
1590+ version ,
1591+ } ) ;
1592+ }
15561593
1557- peers_status
1558- } ) ;
1594+ Some ( (
1595+ peers_status,
1596+ ( status_stream, client, peers, cached_versions, prev_online) ,
1597+ ) )
1598+ } ,
1599+ ) ;
15591600
15601601 Ok ( mapped_stream. boxed ( ) )
15611602 }
0 commit comments