multiversx_sc_meta/cli/
cli_args_standalone.rs

1use clap::{ArgAction, Args, Parser, Subcommand, ValueEnum};
2use std::path::PathBuf;
3
4use multiversx_sc_meta_lib::cli::{CliArgsToRaw, ContractCliAction};
5
6/// Parsed arguments of the meta crate CLI.
7#[derive(Default, PartialEq, Eq, Debug, Parser)]
8#[command(
9    version,
10    about,
11    after_help = "
12The MultiversX smart contract Meta crate can be used in two ways:
13    A. Import it into a contract's specific meta-crate. 
14        There it will receive access to the contract ABI generator. 
15        Based on that it is able to build the contract and apply various tools.
16        This part also contains the multi-contract config infrastructure.
17
18    B. Use it as a standalone tool.
19        It can be used to automatically upgrade contracts from one version to the next.
20
21You are currently using the standalone tool (B).
22"
23)]
24#[command(propagate_version = true)]
25pub struct StandaloneCliArgs {
26    #[command(subcommand)]
27    pub command: Option<StandaloneCliAction>,
28}
29
30#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
31pub enum StandaloneCliAction {
32    #[command(name = "install", about = "Installs framework dependencies")]
33    Install(InstallArgs),
34
35    #[command(
36        about = "General info about the contract an libraries residing in the targeted directory.."
37    )]
38    Info(InfoArgs),
39
40    #[command(
41        about = "Calls the meta crates for all contracts under given path with the given arguments."
42    )]
43    All(AllArgs),
44
45    #[command(
46        about = "Upgrades a contract to the latest version. Multiple contract crates are allowed."
47    )]
48    Upgrade(UpgradeArgs),
49
50    #[command(name = "new", about = "Creates a contract by a pre-existing template")]
51    Template(TemplateArgs),
52
53    #[command(name = "templates", about = "Lists all pre-existing templates")]
54    TemplateList(TemplateListArgs),
55
56    #[command(
57        name = "test-gen",
58        about = "Generates Rust integration tests based on scenarios provided in the scenarios folder of each contract."
59    )]
60    TestGen(TestGenArgs),
61
62    #[command(name = "test", about = "Runs cargo test")]
63    Test(TestArgs),
64
65    #[command(name = "test-coverage", about = "Run test coverage and output report")]
66    TestCoverage(TestCoverageArgs),
67
68    #[command(name = "report", about = "Generate code report")]
69    CodeReportGen(CodeReportArgs),
70
71    #[command(
72        about = "Generates a scenario test initialized with real data fetched from the blockchain."
73    )]
74    Account(AccountArgs),
75
76    #[command(
77        name = "local-deps",
78        about = "Generates a report on the local dependencies of contract crates. Will explore indirect dependencies too."
79    )]
80    LocalDeps(LocalDepsArgs),
81
82    #[command(
83        name = "wallet",
84        about = "Generates a new wallet or performs actions on an existing wallet."
85    )]
86    Wallet(WalletArgs),
87
88    #[command(
89        name = "cs",
90        about = "Can install, start and stop a chain simulator configuration."
91    )]
92    ChainSimulator(ChainSimulatorArgs),
93}
94
95#[derive(Clone, PartialEq, Eq, Debug, Args)]
96pub struct ChainSimulatorArgs {
97    #[command(subcommand)]
98    pub command: ChainSimulatorCommand,
99}
100
101#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
102pub enum ChainSimulatorCommand {
103    #[command(
104        about = "Pulls the latest chain simulator docker image available. Needs Docker installed."
105    )]
106    Install,
107
108    #[command(about = "Starts the chain simulator.")]
109    Start,
110
111    #[command(about = "Stops the chain simulator.")]
112    Stop,
113}
114
115#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
116pub struct InfoArgs {
117    /// Target directory to retrieve info from.
118    /// Will be current directory if not specified.
119    #[arg(long, verbatim_doc_comment)]
120    pub path: Option<String>,
121
122    /// Ignore all directories with these names.
123    #[arg(long, verbatim_doc_comment)]
124    #[clap(global = true, default_value = "target")]
125    pub ignore: Vec<String>,
126}
127
128#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
129pub struct TestArgs {
130    /// Target directory where to generate contract integration tests (default: current directory)
131    #[arg(short, long)]
132    pub path: Option<String>,
133
134    /// Run Debugger (Rust-only) and Go tests; deprecated in favor of -w or --wasm (default: "false")
135    #[arg(short, long, default_value = "false")]
136    pub go: bool,
137
138    /// Run tests that are based on compiled contracts (default: "false")
139    #[arg(short, long, default_value = "false")]
140    pub wasm: bool,
141
142    /// Run interactor tests using chain simulator (default: "false")
143    #[arg(
144        short = 'c',
145        long = "chain-simulator",
146        default_value = "false",
147        verbatim_doc_comment
148    )]
149    pub chain_simulator: bool,
150
151    /// Run mx-scenario-go (default: "false")
152    /// Overrides other arguments
153    #[arg(short, long, default_value = "false", verbatim_doc_comment)]
154    pub scen: bool,
155
156    /// Print the entire output from the Rust tests (default: "false")
157    #[arg(short, long, default_value = "false", verbatim_doc_comment)]
158    pub nocapture: bool,
159}
160
161#[derive(Default, Clone, PartialEq, Eq, Debug, ValueEnum)]
162pub enum OutputFormat {
163    /// Markdown pretty-print summary
164    #[default]
165    Markdown,
166
167    /// JSON summary
168    Json,
169}
170
171#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
172pub struct TestCoverageArgs {
173    /// Output file path
174    #[arg(short, long, verbatim_doc_comment)]
175    pub output: String,
176
177    /// Output format
178    #[arg(short, long, verbatim_doc_comment)]
179    pub format: Option<OutputFormat>,
180
181    /// Ignore files by path patterns
182    #[arg(short = 'i', long = "ignore-filename-regex", verbatim_doc_comment)]
183    pub ignore_filename_regex: Vec<String>,
184}
185
186#[derive(Clone, PartialEq, Eq, Debug, Args)]
187pub struct CodeReportArgs {
188    #[command(subcommand)]
189    pub command: CodeReportAction,
190}
191
192#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
193pub enum CodeReportAction {
194    #[command(name = "compile", about = "Generates the contract report.")]
195    Compile(CompileArgs),
196
197    #[command(name = "compare", about = "Compare two contract reports.")]
198    Compare(CompareArgs),
199
200    #[command(
201        name = "convert",
202        about = "Converts a contract report to a Markdown file."
203    )]
204    Convert(ConvertArgs),
205}
206
207#[derive(Clone, PartialEq, Eq, Debug, Args)]
208pub struct CompileArgs {
209    /// Target directory where to generate code report.
210    #[arg(short, long, verbatim_doc_comment)]
211    pub path: PathBuf,
212
213    /// Path to the Markdown or JSON file where the report results will be written.
214    #[arg(short, long, verbatim_doc_comment)]
215    pub output: PathBuf,
216}
217
218#[derive(Clone, PartialEq, Eq, Debug, Args)]
219pub struct CompareArgs {
220    /// Path to the previous version of code report JSON file
221    /// that will be used for comparison.
222    #[arg(short, long, verbatim_doc_comment)]
223    pub baseline: PathBuf,
224
225    /// Path to the current version of the code report JSON file
226    /// that will be compared.
227    #[arg(short, long, verbatim_doc_comment)]
228    pub new: PathBuf,
229
230    /// Path to the Markdown file where the comparison results will be written.
231    #[arg(short, long, verbatim_doc_comment)]
232    pub output: PathBuf,
233}
234
235#[derive(Clone, PartialEq, Eq, Debug, Args)]
236pub struct ConvertArgs {
237    /// Path to the JSON report file that needs to be converted to Markdown format.
238    #[arg(short, long, verbatim_doc_comment)]
239    pub input: PathBuf,
240
241    /// Path to the Markdown file where the report results will be written.
242    #[arg(short, long, verbatim_doc_comment)]
243    pub output: PathBuf,
244}
245
246#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
247pub struct AllArgs {
248    #[command(subcommand)]
249    pub command: ContractCliAction,
250
251    /// Target directory where to call all contract meta crates.
252    /// Will be current directory if not specified.
253    #[arg(long, verbatim_doc_comment)]
254    #[clap(global = true)]
255    pub path: Option<String>,
256
257    /// Ignore all directories with these names.
258    #[arg(long, verbatim_doc_comment)]
259    #[clap(global = true, default_value = "target")]
260    pub ignore: Vec<String>,
261
262    #[arg(
263        long = "no-abi-git-version",
264        help = "Skips loading the Git version into the ABI",
265        action = ArgAction::SetFalse
266    )]
267    #[clap(global = true)]
268    pub load_abi_git_version: bool,
269
270    /// For the meta crates, allows specifying the target directory where the Rust compiler will build the intermediary files.
271    /// Sharing the same target directory can speed up building multiple contract crates at once.
272    #[arg(long = "target-dir-meta", verbatim_doc_comment)]
273    #[clap(global = true)]
274    pub target_dir_meta: Option<String>,
275
276    /// Overrides both the --target-dir-meta and the --target-dir-wasm args.
277    #[arg(long = "target-dir-all", verbatim_doc_comment)]
278    #[clap(global = true)]
279    pub target_dir_all: Option<String>,
280}
281
282impl AllArgs {
283    pub fn target_dir_all_override(&self) -> Self {
284        let mut result = self.clone();
285        if let Some(target_dir_all) = &self.target_dir_all {
286            result.target_dir_meta = Some(target_dir_all.clone());
287            match &mut result.command {
288                ContractCliAction::Build(build_args) => {
289                    build_args.target_dir_wasm = Some(target_dir_all.clone());
290                }
291                ContractCliAction::BuildDbg(build_args) => {
292                    build_args.target_dir_wasm = Some(target_dir_all.clone());
293                }
294                ContractCliAction::Twiggy(build_args) => {
295                    build_args.target_dir_wasm = Some(target_dir_all.clone());
296                }
297                _ => {}
298            }
299        }
300        result
301    }
302
303    pub fn to_cargo_run_args(&self) -> Vec<String> {
304        let processed = self.target_dir_all_override();
305        let mut raw = vec!["run".to_string()];
306        if let Some(target_dir_meta) = &processed.target_dir_meta {
307            raw.push("--target-dir".to_string());
308            raw.push(target_dir_meta.clone());
309        }
310        raw.append(&mut processed.command.to_raw());
311        if !processed.load_abi_git_version {
312            raw.push("--no-abi-git-version".to_string());
313        }
314        raw
315    }
316
317    /// Produces the arguments for an abi call corresponding to a build.
318    ///
319    /// Used to get the rustc and framework versions configured for a build.
320    pub fn to_cargo_abi_for_build(&self) -> Vec<String> {
321        let processed = self.target_dir_all_override();
322        let mut raw = vec!["run".to_string()];
323        if let Some(target_dir_meta) = &processed.target_dir_meta {
324            raw.push("--target-dir".to_string());
325            raw.push(target_dir_meta.clone());
326        }
327        raw.push("abi".to_string());
328        if !processed.load_abi_git_version {
329            raw.push("--no-abi-git-version".to_string());
330        }
331        raw
332    }
333}
334
335#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
336pub struct UpgradeArgs {
337    /// Target directory where to upgrade contracts.
338    /// Will be current directory if not specified.
339    #[arg(long, verbatim_doc_comment)]
340    pub path: Option<String>,
341
342    /// Ignore all directories with these names.
343    #[arg(long, verbatim_doc_comment)]
344    #[clap(global = true, default_value = "target")]
345    pub ignore: Vec<String>,
346
347    /// Overrides the version to upgrade to.
348    /// By default it will be the last version out.
349    #[arg(long = "to", verbatim_doc_comment)]
350    pub override_target_version: Option<String>,
351
352    /// Skips 'cargo check' after upgrade
353    #[arg(short, long, default_value = "false", verbatim_doc_comment)]
354    pub no_check: bool,
355}
356
357#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
358pub struct LocalDepsArgs {
359    /// Target directory where to generate local deps reports.
360    /// Will be current directory if not specified.
361    #[arg(long, verbatim_doc_comment)]
362    pub path: Option<String>,
363
364    /// Ignore all directories with these names.
365    #[arg(long, verbatim_doc_comment)]
366    #[clap(global = true, default_value = "target")]
367    pub ignore: Vec<String>,
368}
369
370#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
371pub struct TemplateArgs {
372    /// The new name the contract is to receive.
373    /// If missing, the template name will be considered.
374    #[arg(long, verbatim_doc_comment)]
375    pub name: Option<String>,
376
377    /// The contract template to clone.
378    #[arg(long, verbatim_doc_comment)]
379    pub template: String,
380
381    /// The framework version on which the contracts should be created.
382    #[arg(long, verbatim_doc_comment)]
383    pub tag: Option<String>,
384
385    /// Target directory where to create the new contract directory.
386    /// Will be current directory if not specified.
387    #[arg(long, verbatim_doc_comment)]
388    pub path: Option<PathBuf>,
389
390    /// The author of the contract.
391    /// If missing, the default author will be considered.
392    #[arg(long, verbatim_doc_comment)]
393    pub author: Option<String>,
394}
395
396impl CliArgsToRaw for TemplateArgs {
397    fn to_raw(&self) -> Vec<String> {
398        Vec::new()
399    }
400}
401
402#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
403pub struct TemplateListArgs {
404    /// The framework version referred to.
405    #[arg(long = "tag", verbatim_doc_comment)]
406    pub tag: Option<String>,
407}
408
409#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
410pub struct TestGenArgs {
411    /// Target directory where to generate contract integration tests.
412    /// Will be current directory if not specified.
413    #[arg(long, verbatim_doc_comment)]
414    pub path: Option<String>,
415
416    /// Ignore all directories with these names.
417    #[arg(long, verbatim_doc_comment)]
418    #[clap(global = true, default_value = "target")]
419    pub ignore: Vec<String>,
420
421    /// Creates test files if they don't exist.
422    #[arg(long, verbatim_doc_comment)]
423    pub create: bool,
424}
425
426#[derive(Default, PartialEq, Eq, Debug, Clone, Parser)]
427#[command(propagate_version = true)]
428pub struct InstallArgs {
429    #[command(subcommand)]
430    pub command: Option<InstallCommand>,
431}
432
433#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
434pub enum InstallCommand {
435    #[command(about = "Installs all the known tools")]
436    All,
437
438    #[command(about = "Installs the `mx-scenario-go` tool")]
439    MxScenarioGo(InstallMxScenarioGoArgs),
440
441    #[command(name = "wasm32", about = "Installs the `wasm32` target")]
442    Wasm32(InstallWasm32Args),
443
444    #[command(name = "wasm-opt", about = "Installs the `wasm-opt` tool")]
445    WasmOpt(InstallWasmOptArgs),
446
447    #[command(name = "debugger", about = "Installs the lldb debugger script tool")]
448    Debugger(InstallDebuggerArgs),
449}
450
451#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
452pub struct InstallMxScenarioGoArgs {
453    /// The framework version on which the contracts should be created.
454    #[arg(long, verbatim_doc_comment)]
455    pub tag: Option<String>,
456}
457
458#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
459pub struct InstallWasm32Args {}
460
461#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
462pub struct InstallWasmOptArgs {}
463
464#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
465pub struct InstallDebuggerArgs {}
466
467#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
468pub struct AccountArgs {
469    /// Provide the target API you want the data to come from
470    #[arg(long = "api")]
471    #[clap(global = true)]
472    pub api: Option<String>,
473
474    /// Provide the address you want to retrieve data from
475    #[arg(long = "address", verbatim_doc_comment)]
476    pub address: String,
477}
478
479#[derive(Clone, PartialEq, Eq, Debug, Subcommand)]
480pub enum WalletAction {
481    #[command(name = "new", about = "Creates a new wallet")]
482    New(WalletNewArgs),
483
484    #[command(
485        name = "bech32",
486        about = "Encodes/decodes a bech32 address to/from hex"
487    )]
488    Bech32(WalletBech32Args),
489    #[command(name = "convert", about = "Converts a wallet")]
490    Convert(WalletConvertArgs),
491}
492
493#[derive(Clone, PartialEq, Eq, Debug, Parser)]
494#[command(propagate_version = true)]
495pub struct WalletArgs {
496    #[command(subcommand)]
497    pub command: WalletAction,
498}
499
500#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
501pub struct WalletNewArgs {
502    /// The type of wallet to create.
503    #[arg(long = "format", verbatim_doc_comment)]
504    pub wallet_format: Option<String>,
505
506    /// The name of the wallet to create.
507    #[arg(long = "outfile", verbatim_doc_comment)]
508    pub outfile: Option<String>,
509
510    #[arg(long = "hrp", verbatim_doc_comment)]
511    pub hrp: Option<String>,
512}
513
514#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
515pub struct WalletConvertArgs {
516    #[arg(long = "in-format", verbatim_doc_comment)]
517    pub from: String,
518
519    #[arg(long = "out-format", verbatim_doc_comment)]
520    pub to: String,
521
522    #[arg(long = "infile", verbatim_doc_comment)]
523    pub infile: Option<String>,
524
525    #[arg(long = "outfile", verbatim_doc_comment)]
526    pub outfile: Option<String>,
527
528    #[arg(long = "hrp", verbatim_doc_comment)]
529    pub hrp: Option<String>,
530}
531
532#[derive(Default, Clone, PartialEq, Eq, Debug, Args)]
533pub struct WalletBech32Args {
534    #[arg(long = "encode", verbatim_doc_comment)]
535    pub hex_address: Option<String>,
536    #[arg(long = "decode", verbatim_doc_comment)]
537    pub bech32_address: Option<String>,
538}