1#![doc = include_str!("../README.md")]
2#![warn(missing_docs)]
3#![warn(unused_extern_crates)]
4#![forbid(unsafe_code)]
5
6use std::{collections::HashMap, sync::Arc};
7
8use wasm_bindgen::prelude::*;
9
10use huff_neo_core::Compiler;
11use huff_neo_utils::{
12 abi::Abi,
13 artifact::{self, Artifact},
14 prelude::EVMVersion,
15};
16use serde::{Deserialize, Serialize};
17use tsify::Tsify;
18
19#[derive(Serialize, Deserialize, Tsify)]
21#[tsify(into_wasm_abi, from_wasm_abi)]
22pub struct CompilerInput {
23 evm_version: Option<String>,
24 sources: Vec<String>,
25 files: HashMap<String, String>,
26 construct_args: Option<Vec<String>>,
27 alternative_main: Option<String>,
28 alternative_constructor: Option<String>,
29}
30
31#[derive(Serialize, Deserialize, Tsify)]
33#[tsify(into_wasm_abi, from_wasm_abi)]
34pub struct CompilerArtifact {
35 bytecode: String,
36 runtime: String,
37 abi: Option<Abi>,
38 constructor_map: Option<Vec<artifact::SourceMapEntry>>,
39 runtime_map: Option<Vec<artifact::SourceMapEntry>>,
40}
41
42#[derive(Serialize, Deserialize, Tsify)]
44#[tsify(into_wasm_abi, from_wasm_abi)]
45pub struct CompilerOutput {
46 errors: Option<Vec<String>>,
47 contracts: Option<HashMap<String, CompilerArtifact>>,
48}
49
50#[wasm_bindgen]
52pub fn compile(input: CompilerInput) -> CompilerOutput {
53 let evm_version = EVMVersion::from(input.evm_version);
54
55 let compiler = Compiler::new_in_memory(
56 &evm_version,
57 Arc::new(input.sources.clone()),
58 input.files,
59 input.alternative_main,
60 input.alternative_constructor,
61 input.construct_args,
62 None,
63 false,
64 );
65
66 let res: Vec<Arc<Artifact>> = match compiler.execute() {
68 Ok(artifacts) => artifacts,
69 Err(err) => {
70 return CompilerOutput { errors: Some(vec![format!("{}", *err)]), contracts: None };
72 }
73 };
74
75 if res.is_empty() {
77 return CompilerOutput {
78 errors: Some(vec!["No artifacts generated. Check that files are accessible and contain valid Huff code.".to_string()]),
79 contracts: None,
80 };
81 }
82
83 let mut contracts: HashMap<String, CompilerArtifact> = HashMap::new();
84
85 res.into_iter().for_each(|artifact| {
86 contracts.insert(
87 artifact.file.path.clone(),
88 CompilerArtifact {
89 bytecode: artifact.bytecode.clone(),
90 runtime: artifact.runtime.clone(),
91 abi: artifact.abi.clone(),
92 constructor_map: artifact.constructor_map.clone(),
93 runtime_map: artifact.runtime_map.clone(),
94 },
95 );
96 });
97
98 CompilerOutput { errors: None, contracts: Some(contracts) }
99}