huff_neo_utils/
sol_interface.rs1use crate::abi::FunctionParamType;
2use crate::prelude::Artifact;
3use std::{
4 fs,
5 path::{Path, PathBuf},
6 sync::Arc,
7};
8
9pub fn gen_sol_interfaces(artifacts: &Vec<Arc<Artifact>>, interface: Option<String>) -> Vec<(PathBuf, String, String)> {
14 let mut interfaces = Vec::new();
15
16 for artifact in artifacts {
17 if let Some(a) = &artifact.abi {
18 let mut defs = Vec::new();
19 let mut structs = Vec::new();
20 a.events.iter().for_each(|(_, f)| {
21 defs.push(format!(
22 "{}event {}({});",
23 "\t",
24 f.name,
25 f.inputs
26 .iter()
27 .map(|i| {
28 format!(
29 "{}{}",
30 sol_type(&i.kind, &mut structs),
31 if i.indexed { String::from(" indexed") } else { String::default() }
32 )
33 })
34 .collect::<Vec<_>>()
35 .join(", "),
36 ));
37 });
38 a.errors.iter().for_each(|(_, e)| {
39 defs.push(format!(
40 "{}error {}({});",
41 "\t",
42 e.name,
43 e.inputs.iter().map(|i| sol_type(&i.kind, &mut structs)).collect::<Vec<_>>().join(", "),
44 ));
45 });
46 a.functions.iter().for_each(|(_, f)| {
47 defs.push(format!(
48 "{}function {}({}) external{}{};",
49 "\t",
50 f.name,
51 f.inputs.iter().map(|i| param(&i.kind, &mut structs)).collect::<Vec<_>>().join(", "),
52 f.state_mutability.interface_mutability(),
53 if f.outputs.is_empty() {
54 String::default()
55 } else {
56 format!(" returns ({})", f.outputs.iter().map(|o| param(&o.kind, &mut structs)).collect::<Vec<_>>().join(", "))
57 },
58 ));
59 });
60
61 let interface_name = interface
62 .clone()
63 .unwrap_or_else(|| format!("I{}", artifact.file.path.split('/').next_back().unwrap().split('.').next().unwrap()));
64 let struct_defs = structs.into_iter().map(|(_, def)| def);
65 let formatted_str = format!("interface {interface_name} {{\n{}\n}}", struct_defs.chain(defs).collect::<Vec<_>>().join("\n"));
66 interfaces.push((Path::new(&artifact.file.path).parent().unwrap().to_path_buf(), interface_name, formatted_str));
67 }
68 }
69
70 interfaces
71}
72
73fn param(kind: &FunctionParamType, structs: &mut Vec<(FunctionParamType, String)>) -> String {
75 format!("{}{}", sol_type(kind, structs), if kind.is_memory_type() { " memory" } else { "" })
76}
77
78fn sol_type(kind: &FunctionParamType, structs: &mut Vec<(FunctionParamType, String)>) -> String {
81 match kind {
82 FunctionParamType::Tuple(components) => {
83 if let Some(index) = structs.iter().position(|(tuple, _)| tuple == kind) {
84 return format!("Tuple{index}");
85 }
86 let fields: Vec<String> =
88 components.iter().enumerate().map(|(i, component)| format!("\t\t{} _{i};", sol_type(component, structs))).collect();
89 let name = format!("Tuple{}", structs.len());
90 structs.push((kind.clone(), format!("\tstruct {name} {{\n{}\n\t}}", fields.join("\n"))));
91 name
92 }
93 FunctionParamType::Array(inner, sizes) => format!(
94 "{}{}",
95 sol_type(inner, structs),
96 sizes.iter().map(|size| if *size == 0 { "[]".to_string() } else { format!("[{size}]") }).collect::<String>()
97 ),
98 _ => kind.to_string(),
99 }
100}
101
102pub fn export_interfaces(interfaces: &Vec<(PathBuf, String, String)>) -> Result<(), std::io::Error> {
107 for (path, name, interface) in interfaces {
108 fs::write(path.join(format!("{name}.sol")), interface)?;
110 }
111 Ok(())
112}