1use linera_base::{
5 data_types::{ChainDescription, ChainOrigin},
6 identifiers::ChainId,
7};
8pub use linera_client::wallet::*;
9
10pub fn pretty_print(wallet: &Wallet, chain_ids: impl IntoIterator<Item = ChainId>) {
11 let chain_ids: Vec<_> = chain_ids.into_iter().collect();
12 let total_chains = chain_ids.len();
13
14 if total_chains == 0 {
15 println!("No chains in wallet.");
16 return;
17 }
18
19 let plural_s = if total_chains == 1 { "" } else { "s" };
20 println!("\n\x1b[1mWALLET ({total_chains} chain{plural_s} in total)\x1b[0m",);
21
22 let mut chains = chain_ids
23 .into_iter()
24 .map(|chain_id| ChainDetails::new(chain_id, wallet))
25 .collect::<Vec<_>>();
26 chains.sort_unstable_by_key(|chain| {
29 let root_id = chain
30 .origin
31 .and_then(|origin| origin.root())
32 .unwrap_or(u32::MAX);
33 let chain_id = chain.user_chain.chain_id;
34 (!chain.is_default, !chain.is_admin, root_id, chain_id)
35 });
36 for chain in chains {
37 println!();
38 chain.print_paragraph();
39 }
40}
41
42struct ChainDetails<'a> {
43 is_default: bool,
44 is_admin: bool,
45 origin: Option<ChainOrigin>,
46 user_chain: &'a UserChain,
47}
48
49impl<'a> ChainDetails<'a> {
50 fn new(chain_id: ChainId, wallet: &'a Wallet) -> Self {
51 let Some(user_chain) = wallet.chains.get(&chain_id) else {
52 panic!("Chain {} not found.", chain_id);
53 };
54 ChainDetails {
55 is_default: Some(chain_id) == wallet.default,
56 is_admin: chain_id == wallet.genesis_admin_chain(),
57 origin: wallet
58 .genesis_config()
59 .chains
60 .iter()
61 .find(|description| description.id() == chain_id)
62 .map(ChainDescription::origin),
63 user_chain,
64 }
65 }
66
67 fn print_paragraph(&self) {
68 let title = if self.is_admin {
69 "Admin Chain".to_string()
70 } else {
71 match self.origin {
72 Some(ChainOrigin::Root(i)) => format!("Root Chain {i}"),
73 _ => "Child Chain".to_string(),
74 }
75 };
76 let default_marker = if self.is_default { " [DEFAULT]" } else { "" };
77
78 println!("\x1b[1m{}{}\x1b[0m", title, default_marker);
80 println!(" Chain ID: {}", self.user_chain.chain_id);
81 if let Some(owner) = &self.user_chain.owner {
82 println!(" Owner: {owner}");
83 } else {
84 println!(" Owner: No owner key");
85 }
86 println!(" Timestamp: {}", self.user_chain.timestamp);
87 println!(" Blocks: {}", self.user_chain.next_block_height);
88 if let Some(epoch) = self.user_chain.epoch {
89 println!(" Epoch: {epoch}");
90 } else {
91 println!(" Epoch: -");
92 }
93 if let Some(hash) = self.user_chain.block_hash {
94 println!(" Latest Block: {}", hash);
95 }
96 if self.user_chain.pending_proposal.is_some() {
97 println!(" Status: ⚠ Pending proposal");
98 }
99 }
100}