linera_wallet_json/
display.rs1use linera_base::{
7 data_types::{ChainDescription, ChainOrigin},
8 identifiers::ChainId,
9};
10use linera_core::wallet;
11
12use crate::wallet::Data;
13
14struct ChainDetails {
15 is_default: bool,
16 is_admin: bool,
17 origin: Option<ChainOrigin>,
18 chain_id: ChainId,
19 user_chain: wallet::Chain,
20}
21
22impl ChainDetails {
23 fn new(chain_id: ChainId, data: &Data) -> Self {
24 let Some(user_chain) = data.chains.get(chain_id) else {
25 panic!("Chain {chain_id} not found.");
26 };
27 ChainDetails {
28 is_default: Some(chain_id) == *data.default.read().unwrap(),
29 is_admin: chain_id == data.genesis_config.admin_chain_id(),
30 chain_id,
31 origin: data
32 .genesis_config
33 .chains
34 .iter()
35 .find(|description| description.id() == chain_id)
36 .map(ChainDescription::origin),
37 user_chain,
38 }
39 }
40
41 fn print_paragraph(&self) {
42 println!("-----------------------");
43 println!("{:<20} {}", "Chain ID:", self.chain_id);
44
45 let mut tags = Vec::new();
46 if self.is_default {
47 tags.push("DEFAULT");
48 }
49 if self.is_admin {
50 tags.push("ADMIN");
51 }
52 if self.user_chain.is_follow_only() {
53 tags.push("FOLLOW-ONLY");
54 }
55 if !tags.is_empty() {
56 println!("{:<20} {}", "Tags:", tags.join(", "));
57 }
58
59 match self.origin {
60 Some(ChainOrigin::Root(_)) | None => {
61 println!("{:<20} -", "Parent chain:");
62 }
63 Some(ChainOrigin::Child { parent, .. }) => {
64 println!("{:<20} {parent}", "Parent chain:");
65 }
66 }
67
68 if let Some(owner) = &self.user_chain.owner {
69 println!("{:<20} {owner}", "Default owner:");
70 } else {
71 println!("{:<20} No owner key", "Default owner:");
72 }
73
74 println!("{:<20} {}", "Timestamp:", self.user_chain.timestamp);
75 println!("{:<20} {}", "Blocks:", self.user_chain.next_block_height);
76
77 if let Some(epoch) = self.user_chain.epoch {
78 println!("{:<20} {epoch}", "Epoch:");
79 } else {
80 println!("{:<20} -", "Epoch:");
81 }
82
83 if let Some(hash) = self.user_chain.block_hash {
84 println!("{:<20} {hash}", "Latest block hash:");
85 }
86
87 if self.user_chain.pending_fast_proposal.is_some() {
88 println!("{:<20} present", "Pending fast proposal:");
89 }
90 }
91}
92
93pub fn pretty_print(wallet: &crate::PersistentWallet, chain_ids: Vec<ChainId>) {
95 let total_chains = chain_ids.len();
96 let plural_s = if total_chains == 1 { "" } else { "s" };
97 tracing::info!("Found {total_chains} chain{plural_s}");
98
99 let mut chains = chain_ids
100 .into_iter()
101 .map(|chain_id| ChainDetails::new(chain_id, wallet.data()))
102 .collect::<Vec<_>>();
103 chains.sort_unstable_by_key(|chain| {
104 let root_id = chain
105 .origin
106 .and_then(|origin| origin.root())
107 .unwrap_or(u32::MAX);
108 let chain_id = chain.chain_id;
109 (!chain.is_default, !chain.is_admin, root_id, chain_id)
110 });
111 for chain in chains {
112 chain.print_paragraph();
113 }
114 println!("------------------------");
115}