elabs_solc/lib.rs
1// Copyright (C) 2022 The Elabs Project Authors.
2// This file is part of the Elabs library.
3//
4// The Elabs library is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, version 3 of the License.
7//
8// The Elabs library is distributed in the hope that it will be useful,
9// but WITHOUT ANY WARRANTY; without even the implied warranty of
10// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11// GNU General Public License for more details.
12//
13// You should have received a copy of the GNU General Public License along with The Elabs library.
14// If not, see <https://www.gnu.org/licenses/>.
15
16//! # Elabs
17//! Elabs-solc is a wrapper around the Solidity compiler.
18//! It is designed to be used as a library, and not as a command line tool.
19//! It will wrap `solc` cli tools, and provide a simple interface
20//! to compile solidity contracts.
21//! ## Usage
22//! To use the library, you need to import it in your project:
23//! ```toml
24//! [dependencies]
25//! elabs-solc = "0.1"
26//! ```
27//! ## Example
28//! ```rust
29//! use elabs_solc::Solc;
30//!
31//! fn main() {
32//! let solc = Solc::new();
33//! let input_path = "contracts/Simple.sol";
34//! let output_path = "artifacts";
35//! match solc.compile(input_path, output_path, vec![]) {
36//! Ok(_) => println!("{} compiled", input_path),
37//! Err(e) => panic!("{}", e),
38//! }
39//! }
40//! ```
41
42use std::process::Command;
43
44/// The solc struct.
45/// It is a wrapper around the solc compiler.
46pub struct Solc(String);
47
48impl Solc {
49 /// Create a new solc wrapper.
50 /// # Arguments
51 /// * `binary` - The binary to use. eg. `solc`.
52 /// # Returns
53 /// * `Solc` - The solc wrapper.
54 /// # TODO
55 /// * Add error handling.
56 /// * Add support for other compilers. eg `solcjs`.
57 pub fn new() -> Solc {
58 Solc("solc".to_string())
59 }
60
61 /// Parse version number.
62 /// # Arguments
63 /// * `version` - The version string.
64 /// # Returns
65 /// * `String` - The version number.
66 pub fn parse_version(version: &str) -> String {
67 version
68 .replace("Version: ", "")
69 .split("+")
70 .next()
71 .unwrap()
72 .to_string()
73 }
74
75 /// Get the solc version.
76 /// # Returns
77 /// * `String` - The solc version.
78 pub fn version(&self) -> String {
79 let mut cmd = Command::new(&self.0);
80 cmd.arg("--version");
81 let output = cmd.output().unwrap();
82 let out_str = String::from_utf8(output.stdout).unwrap();
83 let out_vec = out_str.split("\n").collect::<Vec<&str>>();
84 if out_vec.len() > 1 {
85 Solc::parse_version(out_vec[1])
86 } else {
87 Solc::parse_version(out_vec[0])
88 }
89 }
90
91 /// Compile solidity code.
92 /// # Arguments
93 /// * `input_path` - The path to the solidity file.
94 /// * `out_path` - The path to the output file.
95 /// * `opts` - Optional arguments.
96 /// # Returns
97 /// * `Ok(String)` - The compiled contract.
98 /// * `Err(String)` - The error message.
99 pub fn compile(
100 &self,
101 input_path: &str,
102 out_path: &str,
103 opts: Vec<&str>,
104 ) -> Result<String, String> {
105 let args = vec!["--bin", "--abi", "--overwrite"];
106
107 let cmd = Command::new(&self.0)
108 .args(args)
109 .args(opts)
110 .arg("--output-dir")
111 .arg(out_path)
112 .arg(input_path)
113 .output();
114
115 match cmd {
116 Err(err) => Err(format!("{}", err)),
117 Ok(res) => {
118 // check if stderr was empty, if not return it as error.
119 if res.stderr.len() > 0 {
120 Err(String::from_utf8(res.stderr).unwrap())
121 } else {
122 Ok(String::from_utf8(res.stdout).unwrap())
123 }
124 }
125 }
126 }
127}