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