fedimint_server_ui/dashboard/modules/
wallet.rs

1use maud::{Markup, html};
2
3// Function to render the Wallet module UI section
4pub async fn render(wallet: &fedimint_wallet_server::Wallet) -> Markup {
5    let network = wallet.network_ui();
6    let consensus_block_count = wallet.consensus_block_count_ui().await;
7    let consensus_fee_rate = wallet.consensus_feerate_ui().await;
8    let wallet_summary = wallet.get_wallet_summary_ui().await;
9    let total_spendable = wallet_summary.total_spendable_balance().to_sat();
10    let total_unsigned_change = wallet_summary.total_unsigned_change_balance().to_sat();
11    let total_unconfirmed_change = wallet_summary.total_unconfirmed_change_balance().to_sat();
12    let total_available = total_spendable + total_unconfirmed_change + total_unsigned_change;
13    let total_unsigned_outgoing = wallet_summary.total_unsigned_peg_out_balance().to_sat();
14    let total_unconfirmed_outgoing = wallet_summary.total_unconfirmed_peg_out_balance().to_sat();
15
16    html! {
17        div class="card h-100" {
18            div class="card-header dashboard-header" { "Wallet" }
19            div class="card-body" {
20                table class="table mb-4" {
21                    tr {
22                        th { "Network" }
23                        td { (network.to_string()) }
24                    }
25                    tr {
26                        th { "Consensus Block Count" }
27                        td { (consensus_block_count) }
28                    }
29                    tr {
30                        th { "Consensus Fee Rate" }
31                        td { (consensus_fee_rate.sats_per_kvb) " sats/kvB" }
32                    }
33                    tr {
34                        th { "Spendable Amount" }
35                        td { (total_spendable) " sats" }
36                    }
37                    tr {
38                        th { "Unsigned Change Amount" }
39                        td { (total_unsigned_change) " sats" }
40                    }
41                    tr {
42                        th { "Unconfirmed Change Amount" }
43                        td { (total_unconfirmed_change) " sats" }
44                    }
45                    tr {
46                        th { "Total Amount in Custody" }
47                        td { (total_available) " sats" }
48                    }
49                    tr {
50                        th { "Unsigned Outgoing Amount" }
51                        td { (total_unsigned_outgoing) " sats" }
52                    }
53                    tr {
54                        th { "Unconfirmed Outgoing Amount" }
55                        td { (total_unconfirmed_outgoing) " sats" }
56                    }
57                }
58
59                // Collapsible info section
60                div class="mb-4" {
61                    p {
62                        button class="btn btn-sm btn-outline-primary" type="button" data-bs-toggle="collapse" data-bs-target="#balanceInfo" aria-expanded="false" aria-controls="balanceInfo" {
63                            "What do these amounts mean? "
64                            i class="bi bi-info-circle" {}
65                        }
66                    }
67                    div class="collapse" id="balanceInfo" {
68                        div class="alert alert-info" {
69                            dl class="row mb-0" {
70                                dt class="col-sm-3" { "Spendable Amount" }
71                                dd class="col-sm-9" { "UTXOs that are confirmed and are available to be spend by your users." }
72
73                                dt class="col-sm-3" { "Change Amounts" }
74                                dd class="col-sm-9" {
75                                    p class="mb-1" { strong { "Unsigned: " } "Change outputs from pegout transactions still waiting for guardian signatures." }
76                                    p class="mb-0" { strong { "Unconfirmed: " } "Change outputs with threshold of signatures, waiting for blockchain confirmations." }
77                                }
78
79                                dt class="col-sm-3" { "Total Amount in Custody" }
80                                dd class="col-sm-9" {
81                                    "Sum of Spendable Amount and both unsigned and unconfirmed change amounts. This represents all funds that will eventually be available to you once all transactions are confirmed."
82                                }
83
84                                dt class="col-sm-3" { "Outgoing Amounts" }
85                                dd class="col-sm-9" {
86                                    p class="mb-1" { strong { "Unsigned: " } "Pegout outputs from pegout transactions still waiting for guardian signatures." }
87                                    p class="mb-0" { strong { "Unconfirmed: " } "Pegout outputs with threshold of signatures, waiting for blockchain confirmations." }
88                                }
89                            }
90                        }
91                    }
92                }
93
94                // UTXO Tables
95                div class="mb-4" {
96                    @if !wallet_summary.unconfirmed_peg_out_txos.is_empty() {
97                        div class="mb-4" {
98                            h5 { "Unconfirmed Pegout UTXOs" }
99                            div class="table-responsive" {
100                                table class="table table-sm" {
101                                    thead {
102                                        tr {
103                                            th { "Amount (sats)" }
104                                            th { "Transaction" }
105                                            th { "Vout" }
106                                        }
107                                    }
108                                    tbody {
109                                        @for txo in &wallet_summary.unconfirmed_peg_out_txos {
110                                            tr {
111                                                td { (txo.amount.to_sat()) }
112                                                td {
113                                                    a href={ "https://mempool.space/tx/" (txo.outpoint.txid) } class="btn btn-sm btn-outline-primary" target="_blank" {
114                                                        "mempool.space"
115                                                    }
116                                                }
117                                                td { (txo.outpoint.vout) }
118                                            }
119                                        }
120                                    }
121                                }
122                            }
123                        }
124                    }
125
126                    // Pending Change UTXOs Table
127                    @if !wallet_summary.unconfirmed_change_utxos.is_empty() {
128                        div class="mb-4" {
129                            h5 { "Unconfirmed Change UTXOs" }
130                            div class="table-responsive" {
131                                table class="table table-sm" {
132                                    thead {
133                                        tr {
134                                            th { "Amount (sats)" }
135                                            th { "Transaction" }
136                                            th { "Vout" }
137                                        }
138                                    }
139                                    tbody {
140                                        @for txo in &wallet_summary.unconfirmed_change_utxos {
141                                            tr {
142                                                td { (txo.amount.to_sat()) }
143                                                td {
144                                                    a href={ "https://mempool.space/tx/" (txo.outpoint.txid) } class="btn btn-sm btn-outline-primary" target="_blank" {
145                                                        "mempool.space"
146                                                    }
147                                                }
148                                                td { (txo.outpoint.vout) }
149                                            }
150                                        }
151                                    }
152                                }
153                            }
154                        }
155                    }
156
157                    // Spendable UTXOs Table
158                    @if !wallet_summary.spendable_utxos.is_empty() {
159                        div class="mb-4" {
160                            h5 { "Spendable UTXOs" }
161                            div class="table-responsive" {
162                                table class="table table-sm" {
163                                    thead {
164                                        tr {
165                                            th { "Amount (sats)" }
166                                            th { "Transaction" }
167                                            th { "Vout" }
168                                        }
169                                    }
170                                    tbody {
171                                        @for utxo in &wallet_summary.spendable_utxos {
172                                            tr {
173                                                td { (utxo.amount.to_sat()) }
174                                                td {
175                                                    a href={ "https://mempool.space/tx/" (utxo.outpoint.txid) } class="btn btn-sm btn-outline-primary" target="_blank" {
176                                                        "mempool.space"
177                                                    }
178                                                }
179                                                td { (utxo.outpoint.vout) }
180                                            }
181                                        }
182                                    }
183                                }
184                            }
185                        }
186                    }
187                }
188            }
189        }
190    }
191}