fedimint_gateway_ui/
bitcoin.rs

1use fedimint_gateway_common::ChainSource;
2use maud::{Markup, html};
3
4use crate::DynGatewayApi;
5
6pub async fn render<E>(api: &DynGatewayApi<E>) -> Markup
7where
8    E: std::fmt::Display,
9{
10    let (blockchain_info, chain_source, network) = api.get_chain_source().await;
11
12    // Determine block height and synced status
13    let (block_height, status_badge) = match blockchain_info {
14        Some(info) => {
15            let badge = if info.synced {
16                html! { span class="badge bg-success" { "🟢 Synced" } }
17            } else {
18                html! { span class="badge bg-warning" { "🟡 Syncing" } }
19            };
20            (info.block_height, badge)
21        }
22        None => (
23            0,
24            html! { span class="badge bg-danger" { "❌ Not Connected" } },
25        ),
26    };
27
28    html! {
29        div class="card h-100" {
30            div class="card-header dashboard-header d-flex justify-content-between align-items-center" {
31                span { "Bitcoin Connection" }
32
33                @if matches!(chain_source, ChainSource::Bitcoind { .. }) {
34                    button
35                        id="btc-password-toggle-btn"
36                        class="btn btn-sm btn-secondary"
37                        type="button"
38                        onclick="toggleBtcPassword()"
39                    {
40                        "Show"
41                    }
42                }
43            }
44
45            div class="card-body" {
46                table class="table table-sm mb-0" {
47                    tbody {
48                        tr {
49                            th { "Network" }
50                            td { (network) }
51                        }
52                        tr {
53                            th { "Block Height" }
54                            td { (block_height) }
55                        }
56                        tr {
57                            th { "Status" }
58                            td { (status_badge) }
59                        }
60
61                        @match &chain_source {
62                            ChainSource::Bitcoind { username, password, server_url } => {
63                                tr {
64                                    th { "Type" }
65                                    td { "Bitcoind" }
66                                }
67                                tr {
68                                    th { "Server URL" }
69                                    td { (server_url) }
70                                }
71                                tr {
72                                    th { "Username" }
73                                    td { (username) }
74                                }
75                                tr {
76                                    th { "Password" }
77                                    td id="btc-password" data-password=(password) { "••••••" }
78                                }
79                            },
80                            ChainSource::Esplora { server_url } => {
81                                tr {
82                                    th { "Type" }
83                                    td { "Esplora" }
84                                }
85                                tr {
86                                    th { "Server URL" }
87                                    td { (server_url) }
88                                }
89                            }
90                        }
91                    }
92                }
93            }
94        }
95
96        @if matches!(chain_source, ChainSource::Bitcoind { .. }) {
97            script {
98                (maud::PreEscaped(r#"
99                    function toggleBtcPassword() {
100                        const btn = document.getElementById("btc-password-toggle-btn");
101                        const pwdEl = document.getElementById("btc-password");
102                        const showing = btn.dataset.showing === "true";
103
104                        if (showing) {
105                            pwdEl.textContent = "••••••";
106                        } else {
107                            pwdEl.textContent = pwdEl.dataset.password;
108                        }
109
110                        btn.textContent = showing ? "Show" : "Hide";
111                        btn.dataset.showing = (!showing).toString();
112                    }
113                "#))
114            }
115        }
116    }
117}