1mod database_params;
19mod import_params;
20mod keystore_params;
21mod message_params;
22mod mixnet_params;
23mod network_params;
24mod node_key_params;
25mod offchain_worker_params;
26mod prometheus_params;
27mod pruning_params;
28mod rpc_params;
29mod runtime_params;
30mod shared_params;
31mod telemetry_params;
32mod transaction_pool_params;
33
34use crate::arg_enums::{CryptoScheme, OutputType};
35use clap::Args;
36use sc_service::config::{IpNetwork, RpcBatchRequestConfig};
37use sp_core::crypto::{Ss58AddressFormat, Ss58AddressFormatRegistry};
38use sp_runtime::{
39 generic::BlockId,
40 traits::{Block as BlockT, NumberFor},
41};
42use std::{fmt::Debug, str::FromStr};
43
44pub use crate::params::{
45 database_params::*, import_params::*, keystore_params::*, message_params::*, mixnet_params::*,
46 network_params::*, node_key_params::*, offchain_worker_params::*, prometheus_params::*,
47 pruning_params::*, rpc_params::*, runtime_params::*, shared_params::*, telemetry_params::*,
48 transaction_pool_params::*,
49};
50
51pub fn parse_ss58_address_format(x: &str) -> Result<Ss58AddressFormat, String> {
53 match Ss58AddressFormatRegistry::try_from(x) {
54 Ok(format_registry) => Ok(format_registry.into()),
55 Err(_) => Err(format!(
56 "Unable to parse variant. Known variants: {:?}",
57 Ss58AddressFormat::all_names()
58 )),
59 }
60}
61
62#[derive(Debug, Clone)]
65pub struct GenericNumber(String);
66
67impl FromStr for GenericNumber {
68 type Err = String;
69
70 fn from_str(block_number: &str) -> Result<Self, Self::Err> {
71 if let Some(pos) = block_number.chars().position(|d| !d.is_digit(10)) {
72 Err(format!("Expected block number, found illegal digit at position: {}", pos))
73 } else {
74 Ok(Self(block_number.to_owned()))
75 }
76 }
77}
78
79impl GenericNumber {
80 pub fn parse<N>(&self) -> Result<N, String>
85 where
86 N: FromStr,
87 N::Err: std::fmt::Debug,
88 {
89 FromStr::from_str(&self.0).map_err(|e| format!("Failed to parse block number: {:?}", e))
90 }
91}
92
93#[derive(Debug, Clone)]
95pub struct BlockNumberOrHash(String);
96
97impl FromStr for BlockNumberOrHash {
98 type Err = String;
99
100 fn from_str(block_number: &str) -> Result<Self, Self::Err> {
101 if let Some(rest) = block_number.strip_prefix("0x") {
102 if let Some(pos) = rest.chars().position(|c| !c.is_ascii_hexdigit()) {
103 Err(format!(
104 "Expected block hash, found illegal hex character at position: {}",
105 2 + pos,
106 ))
107 } else {
108 Ok(Self(block_number.into()))
109 }
110 } else {
111 GenericNumber::from_str(block_number).map(|v| Self(v.0))
112 }
113 }
114}
115
116impl BlockNumberOrHash {
117 pub fn parse<B: BlockT>(&self) -> Result<BlockId<B>, String>
119 where
120 <B::Hash as FromStr>::Err: std::fmt::Debug,
121 NumberFor<B>: FromStr,
122 <NumberFor<B> as FromStr>::Err: std::fmt::Debug,
123 {
124 if self.0.starts_with("0x") {
125 Ok(BlockId::Hash(
126 FromStr::from_str(&self.0[2..])
127 .map_err(|e| format!("Failed to parse block hash: {:?}", e))?,
128 ))
129 } else {
130 GenericNumber(self.0.clone()).parse().map(BlockId::Number)
131 }
132 }
133}
134
135#[derive(Debug, Clone, Args)]
137pub struct CryptoSchemeFlag {
138 #[arg(long, value_name = "SCHEME", value_enum, ignore_case = true, default_value_t = CryptoScheme::Sr25519)]
140 pub scheme: CryptoScheme,
141}
142
143#[derive(Debug, Clone, Args)]
145pub struct OutputTypeFlag {
146 #[arg(long, value_name = "FORMAT", value_enum, ignore_case = true, default_value_t = OutputType::Text)]
148 pub output_type: OutputType,
149}
150
151#[derive(Debug, Clone, Args)]
153pub struct NetworkSchemeFlag {
154 #[arg(
156 short = 'n',
157 long,
158 value_name = "NETWORK",
159 ignore_case = true,
160 value_parser = parse_ss58_address_format,
161 )]
162 pub network: Option<Ss58AddressFormat>,
163}
164
165#[cfg(test)]
166mod tests {
167 use super::*;
168
169 type Header = sp_runtime::generic::Header<u32, sp_runtime::traits::BlakeTwo256>;
170 type Block = sp_runtime::generic::Block<Header, sp_runtime::OpaqueExtrinsic>;
171
172 #[test]
173 fn parse_block_number() {
174 let block_number_or_hash = BlockNumberOrHash::from_str("1234").unwrap();
175 let parsed = block_number_or_hash.parse::<Block>().unwrap();
176 assert_eq!(BlockId::Number(1234), parsed);
177 }
178
179 #[test]
180 fn parse_block_hash() {
181 let hash = sp_core::H256::default();
182 let hash_str = format!("{:?}", hash);
183 let block_number_or_hash = BlockNumberOrHash::from_str(&hash_str).unwrap();
184 let parsed = block_number_or_hash.parse::<Block>().unwrap();
185 assert_eq!(BlockId::Hash(hash), parsed);
186 }
187
188 #[test]
189 fn parse_block_hash_fails() {
190 assert_eq!(
191 "Expected block hash, found illegal hex character at position: 2",
192 BlockNumberOrHash::from_str("0xHello").unwrap_err(),
193 );
194 }
195
196 #[test]
197 fn parse_block_number_fails() {
198 assert_eq!(
199 "Expected block number, found illegal digit at position: 3",
200 BlockNumberOrHash::from_str("345Hello").unwrap_err(),
201 );
202 }
203}