quantus_cli/cli/
metadata.rs

1//! `quantus metadata` subcommand - metadata exploration
2use crate::{chain::client::ChainConfig, log_print, log_verbose};
3use colored::Colorize;
4use subxt::OnlineClient;
5
6/// Explore chain metadata and display all available pallets and calls
7pub async fn explore_chain_metadata(
8	client: &OnlineClient<ChainConfig>,
9	no_docs: bool,
10	pallet_filter: Option<String>,
11) -> crate::error::Result<()> {
12	log_verbose!("🔍 Exploring chain metadata...");
13
14	let metadata = client.metadata();
15	let all_pallets: Vec<_> = metadata.pallets().collect();
16
17	// Filter pallets if pallet_filter is provided
18	let pallets: Vec<_> = if let Some(filter) = &pallet_filter {
19		all_pallets
20			.into_iter()
21			.filter(|pallet| pallet.name().to_lowercase() == filter.to_lowercase())
22			.collect()
23	} else {
24		all_pallets
25	};
26
27	if pallets.is_empty() {
28		if let Some(filter) = pallet_filter {
29			log_print!("❌ Pallet '{}' not found.", filter.bright_red());
30			log_print!("Available pallets:");
31			let all_pallets: Vec<_> = metadata.pallets().collect();
32			for pallet in all_pallets {
33				log_print!("  - {}", pallet.name().bright_blue());
34			}
35			return Ok(());
36		}
37	}
38
39	if pallet_filter.is_some() {
40		log_print!(
41			"{}",
42			format!("🏛️  Pallet Documentation: {}", pallets[0].name()).bold().underline()
43		);
44	} else {
45		log_print!("{}", "🏛️  Available Pallets & Calls".bold().underline());
46	}
47	log_print!("");
48
49	for pallet in pallets.iter() {
50		log_print!("- Pallet: {}", pallet.name().bold().bright_blue());
51
52		// Print calls
53		if let Some(calls) = pallet.call_variants() {
54			log_print!("\t- Calls ({}):", calls.len());
55			if !no_docs {
56				for call_variant in calls {
57					log_print!("\t\t- {}", call_variant.name);
58					let docs = &call_variant.docs;
59					if !docs.is_empty() {
60						log_print!("      {}", docs.join("\n      ").italic().dimmed());
61					}
62				}
63			} else {
64				for call_variant in calls {
65					log_print!("\t\t- {}", call_variant.name);
66				}
67			}
68		} else {
69			log_print!("\t\t- No calls in this pallet.");
70		}
71
72		// Show storage items - SubXT has different API
73		if let Some(storage_metadata) = pallet.storage() {
74			let entries = storage_metadata.entries();
75			log_print!("\t- Storage ({}):", entries.len());
76			for entry in entries {
77				log_print!("\t\t- Name: {}", entry.name());
78
79				if !no_docs {
80					log_verbose!("\t\t- Type: {:?}", entry.entry_type());
81					if !entry.docs().is_empty() {
82						log_verbose!(
83							"\t\t- Docs: {}",
84							entry.docs().join("\n      ").italic().dimmed()
85						);
86					}
87				}
88			}
89		} else {
90			log_print!("\t- Storage (0):");
91		}
92
93		log_print!("");
94	}
95
96	// Add a summary at the end
97	log_print!("{}", "🔍 Exploration Complete".bold());
98	log_print!("Found {} pallets.", pallets.len());
99
100	Ok(())
101}
102
103/// Get basic metadata statistics
104pub async fn get_metadata_stats(client: &OnlineClient<ChainConfig>) -> crate::error::Result<()> {
105	log_verbose!("🔍 Getting metadata statistics...");
106
107	let metadata = client.metadata();
108	let pallets: Vec<_> = metadata.pallets().collect();
109
110	log_print!("📊 Metadata Statistics:");
111	log_print!("   📦 Total pallets: {}", pallets.len());
112	log_print!("   🔗 API: Type-safe SubXT");
113
114	// Count calls across all pallets
115	let mut total_calls = 0;
116	let mut total_storage = 0;
117
118	for pallet in &pallets {
119		if let Some(calls) = pallet.call_variants() {
120			total_calls += calls.len();
121		}
122		if let Some(storage_metadata) = pallet.storage() {
123			total_storage += storage_metadata.entries().len();
124		}
125	}
126
127	log_print!("   🎯 Total calls: {}", total_calls);
128	log_print!("   💾 Total storage items: {}", total_storage);
129
130	Ok(())
131}
132
133/// Handle metadata command execution
134pub async fn handle_metadata_command(
135	node_url: &str,
136	no_docs: bool,
137	stats_only: bool,
138	pallet_filter: Option<String>,
139) -> crate::error::Result<()> {
140	let quantus_client = crate::chain::client::QuantusClient::new(node_url).await?;
141
142	if stats_only {
143		get_metadata_stats(quantus_client.client()).await
144	} else {
145		explore_chain_metadata(quantus_client.client(), no_docs, pallet_filter).await
146	}
147}