1use crate::prelude::*;
2
3#[derive(Parser, Debug)]
5#[clap(author, version, about, long_about = None, name = "rtmd")]
6pub struct Args {
7 #[clap(short, long)]
9 output: PathBuf,
10
11 #[clap(short, long)]
13 network: Option<String>,
14
15 #[clap(short, long, action)]
17 export_blobs: bool,
18
19 #[clap(required = true)]
21 input: PathBuf,
22}
23
24#[derive(Debug)]
25pub enum Error {
26 IoError(std::io::Error),
27 DecodeError(sbor::DecodeError),
28 DecompileError(DecompileError),
29 ParseNetworkError(ParseNetworkError),
30 ManifestValidationError(ManifestValidationError),
31 InstructionSchemaValidationError(radix_engine::utils::LocatedInstructionSchemaValidationError),
32}
33
34impl fmt::Display for Error {
35 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 write!(f, "{:?}", self)
38 }
39}
40
41impl From<Error> for String {
42 fn from(err: Error) -> String {
43 err.to_string()
44 }
45}
46
47pub fn run() -> Result<(), String> {
48 let args = Args::parse();
49
50 let content = std::fs::read(&args.input).map_err(Error::IoError)?;
51 let network = match args.network {
52 Some(n) => NetworkDefinition::from_str(&n).map_err(Error::ParseNetworkError)?,
53 None => NetworkDefinition::simulator(),
54 };
55
56 let manifest = AnyManifest::attempt_decode_from_arbitrary_payload(&content)?;
57
58 manifest
59 .validate(ValidationRuleset::all())
60 .map_err(Error::ManifestValidationError)?;
61
62 validate_call_arguments_to_native_components(&manifest)
63 .map_err(Error::InstructionSchemaValidationError)?;
64
65 let decompiled = decompile_any(&manifest, &network).map_err(Error::DecompileError)?;
66
67 write_ensuring_folder_exists(&args.output, &decompiled).map_err(Error::IoError)?;
68
69 if args.export_blobs {
70 let directory = args.output.parent().unwrap();
71 for (blob_hash, content) in manifest.get_blobs() {
72 std::fs::write(directory.join(format!("{}.blob", blob_hash)), content)
73 .map_err(Error::IoError)?;
74 }
75 }
76
77 Ok(())
78}