Skip to main content

btc_vanity/
flags.rs

1//! # CLI and Input File Flags Module
2//!
3//! This module handles the extraction and management of flags and configuration options
4//! from the command-line interface (CLI) and input files. It provides mechanisms to:
5//! - Parse flags and input patterns from the CLI.
6//! - Combine and prioritize CLI-level and file-based flags.
7
8use crate::vanity_addr_generator::chain::Chain;
9use crate::VanityMode;
10use clap::ArgMatches;
11
12/// Represents the configuration flags for vanity address generation.
13#[derive(Debug, Clone, Default)]
14pub struct VanityFlags {
15    /// The number of threads to use for generation.
16    pub threads: usize,
17    /// The name of the output file, if specified.
18    pub output_file_name: Option<String>,
19
20    /// If `true`, CLI flags override file-based flags.
21    pub force_flags: bool,
22    /// If `true`, pattern matching is case-sensitive.
23    pub is_case_sensitive: bool,
24    /// If `true`, disables fast mode. Fast mode puts a length limit for the searching string.
25    pub disable_fast_mode: bool,
26    /// Specifies the mode of matching (e.g., `prefix`, `suffix`, `anywhere`, `regex`).
27    pub vanity_mode: Option<VanityMode>,
28    /// Specifies the blockchain type (e.g., `Bitcoin`, `Ethereum`, `Solana`).
29    pub chain: Option<Chain>,
30}
31
32/// Enum representing the source of the vanity patterns.
33#[derive(Debug)]
34pub enum PatternsSource {
35    /// A single pattern provided directly via the CLI.
36    SingleString(String),
37    /// Patterns read from an input file specified by its path.
38    InputFile(String),
39}
40
41/// Parses CLI arguments into [VanityFlags] and determines the source of the vanity patterns.
42///
43/// # Arguments
44/// - `matches`: The `ArgMatches` object provided by the `clap` library.
45///
46/// # Returns
47/// - A tuple containing:
48///   - `VanityFlags`: The parsed configuration flags.
49///   - `PatternsSource`: The source of the vanity patterns (either a single string or an input file).
50///
51/// # Behavior
52/// - Determines the blockchain (`chain`) based on flags (e.g., `ethereum`, `solana`, `bitcoin`).
53/// - Determines the vanity mode (`vanity_mode`) based on flags (e.g., `regex`, `anywhere`, `suffix`, `prefix`).
54/// - Parses the number of threads, defaulting to 16 if not specified.
55/// - Detects whether patterns are provided via a single string or an input file.
56pub fn parse_cli(matches: ArgMatches) -> (VanityFlags, PatternsSource) {
57    // 1) Extract chain
58    let chain = if matches.get_flag("ethereum") {
59        Some(Chain::Ethereum)
60    } else if matches.get_flag("solana") {
61        Some(Chain::Solana)
62    } else {
63        Some(Chain::Bitcoin)
64    };
65
66    // 2) Extract vanity mode
67    let vanity_mode = if matches.get_flag("regex") {
68        Some(VanityMode::Regex)
69    } else if matches.get_flag("anywhere") {
70        Some(VanityMode::Anywhere)
71    } else if matches.get_flag("suffix") {
72        Some(VanityMode::Suffix)
73    } else {
74        Some(VanityMode::Prefix)
75    };
76
77    // 3) Threads
78    let threads = matches
79        .get_one::<String>("threads")
80        .unwrap_or(&"16".to_owned())
81        .parse::<usize>()
82        .unwrap_or(16);
83
84    // 4) Build CLI-level `VanityFlags`
85    let cli_flags = VanityFlags {
86        force_flags: matches.get_flag("force-flags"),
87        is_case_sensitive: matches.get_flag("case-sensitive"),
88        disable_fast_mode: matches.get_flag("disable-fast-mode"),
89        output_file_name: matches.get_one::<String>("output-file").cloned(),
90        vanity_mode,
91        chain,
92        threads,
93    };
94
95    // 5) Figure out if user gave a single pattern or a file
96    if let Some(path) = matches.get_one::<String>("input-file") {
97        (cli_flags, PatternsSource::InputFile(path.to_string()))
98    } else {
99        let string = matches.get_one::<String>("string");
100        (
101            cli_flags,
102            PatternsSource::SingleString(string.unwrap_or(&String::new()).to_string()),
103        )
104    }
105}
106
107/// Combines CLI-level flags with file-based flags, giving priority to CLI flags if `force_flags` is set.
108///
109/// # Arguments
110/// - `file_flags`: The `VanityFlags` object derived from the input file.
111///
112/// # Returns
113/// - A unified `VanityFlags` object that combines CLI and file flags.
114///
115/// # Behavior
116/// - If `force_flags` is `true`, the CLI flags override all file-based flags.
117/// - Otherwise, the flags are merged, with file-based flags taking precedence where applicable.
118///
119/// # Example
120/// ```rust
121/// use btc_vanity::flags::VanityFlags;
122///
123/// let cli_flags = VanityFlags {
124///     threads: 8,
125///     force_flags: true,
126///     ..Default::default()
127/// };
128/// let file_flags = VanityFlags {
129///     threads: 4,
130///     ..Default::default()
131/// };
132///
133/// let unified_flags = cli_flags.unify(&file_flags);
134/// assert_eq!(unified_flags.threads, 8); // CLI flags take precedence.
135/// ```
136impl VanityFlags {
137    pub fn unify(&self, file_flags: &VanityFlags) -> VanityFlags {
138        if self.force_flags {
139            // If CLI has force_flags = true, ignore the file-based flags
140            self.clone()
141        } else {
142            VanityFlags {
143                threads: self.threads,
144                output_file_name: file_flags
145                    .output_file_name
146                    .clone()
147                    .or_else(|| self.output_file_name.clone()),
148
149                force_flags: self.force_flags,
150                is_case_sensitive: file_flags.is_case_sensitive,
151                disable_fast_mode: file_flags.disable_fast_mode,
152
153                vanity_mode: file_flags.vanity_mode.or(self.vanity_mode), // Use `file_flags` if Some, otherwise fall back to `self`.
154
155                chain: file_flags.chain.or(self.chain), // Use `file_flags` if Some, otherwise fall back to `self`.
156            }
157        }
158    }
159}