diff --git a/cli/src/cmd/abi.rs b/cli/src/cmd/abi.rs
new file mode 100644
index 0000000000000000000000000000000000000000..36eb4a5269dbfb7acd541efda90f22acf138171a
--- /dev/null
+++ b/cli/src/cmd/abi.rs
@@ -0,0 +1,70 @@
+// Copyright 2018-2019 Parity Technologies (UK) Ltd.
+// This file is part of ink!.
+//
+// ink! is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// ink! is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with ink!. If not, see .
+
+use crate::cmd::{
+ Result,
+};
+use cargo_metadata::MetadataCommand;
+use std::path::PathBuf;
+
+/// Executes build of the smart-contract which produces a wasm binary that is ready for deploying.
+///
+/// It does so by invoking build by cargo and then post processing the final binary.
+pub(crate) fn execute_generate_abi(dir: Option<&PathBuf>) -> Result {
+ println!(" Generating abi");
+
+ super::exec_cargo("run", &[
+ "--package",
+ "abi-gen",
+ "--verbose",
+ ], dir)?;
+
+ let metadata = MetadataCommand::new().exec()?;
+ let mut abi_path = metadata.target_directory.clone();
+ abi_path.push("abi.json");
+
+ Ok(format!(
+ "Your abi file is ready.\nYou can find it here:\n{}",
+ abi_path.display()
+ ))
+}
+
+#[cfg(test)]
+mod tests {
+ use crate::{
+ cmd::{
+ execute_new,
+ execute_generate_abi,
+ tests::with_tmp_dir,
+ },
+ AbstractionLayer,
+ };
+
+ #[test]
+ fn generate_abi() {
+ with_tmp_dir(|path| {
+ execute_new(AbstractionLayer::Lang, "new_project", Some(path))
+ .expect("new project creation failed");
+ let working_dir = path.join("new_project");
+ super::execute_generate_abi(Some(&working_dir)).expect("generate abi failed");
+
+ let mut abi_file = working_dir.clone();
+ abi_file.push("target");
+ abi_file.push("abi.json");
+ assert!(abi_file.exists())
+ });
+ }
+}
diff --git a/cli/src/cmd/build.rs b/cli/src/cmd/build.rs
index 2f57f1c3b5c324981221b79fdfeebdf71133a483..fdd27d904d1143b41cbf3992556b27233394b1c0 100644
--- a/cli/src/cmd/build.rs
+++ b/cli/src/cmd/build.rs
@@ -25,14 +25,7 @@ use parity_wasm::elements::{
Module,
Section,
};
-use std::{
- io::{
- self,
- Write,
- },
- path::PathBuf,
- process::Command,
-};
+use std::path::PathBuf;
/// This is the maximum number of pages available for a contract to allocate.
const MAX_MEMORY_PAGES: u32 = 16;
@@ -96,43 +89,12 @@ pub fn collect_crate_metadata(working_dir: Option<&PathBuf>) -> Result) -> Result<()> {
- let mut cmd = Command::new("cargo");
- let mut is_nightly_cmd = Command::new("cargo");
- if let Some(dir) = working_dir {
- cmd.current_dir(dir);
- is_nightly_cmd.current_dir(dir);
- }
-
- let is_nightly_default = is_nightly_cmd
- .arg("--version")
- .output()
- .map_err(|_| ())
- .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ()))
- .unwrap_or_default()
- .contains("-nightly");
-
- if !is_nightly_default {
- cmd.arg("+nightly");
- }
-
- let output = cmd
- .args(&[
- "build",
- "--no-default-features",
- "--release",
- "--target=wasm32-unknown-unknown",
- "--verbose",
- ])
- .output()?;
-
- if !output.status.success() {
- // Dump the output streams produced by cargo into the stdout/stderr.
- io::stdout().write_all(&output.stdout)?;
- io::stderr().write_all(&output.stderr)?;
- return Err(Error::BuildFailed)
- }
-
- Ok(())
+ super::exec_cargo("build", &[
+ "--no-default-features",
+ "--release",
+ "--target=wasm32-unknown-unknown",
+ "--verbose",
+ ], working_dir)
}
/// Ensures the wasm memory import of a given module has the maximum number of pages.
diff --git a/cli/src/cmd/mod.rs b/cli/src/cmd/mod.rs
index 690c87eccc0dd85fdcae3c0360fc69c712cb2594..993a8034eac246da275e06a93e3b494b4a398051 100644
--- a/cli/src/cmd/mod.rs
+++ b/cli/src/cmd/mod.rs
@@ -14,12 +14,23 @@
// You should have received a copy of the GNU General Public License
// along with ink!. If not, see .
+use std::{
+ io::{
+ self,
+ Write,
+ },
+ path::PathBuf,
+ process::Command,
+};
+
+mod abi;
mod build;
mod deploy;
mod error;
mod new;
pub(crate) use self::{
+ abi::execute_generate_abi,
build::execute_build,
deploy::execute_deploy,
error::{
@@ -29,6 +40,41 @@ pub(crate) use self::{
new::execute_new,
};
+fn exec_cargo(command: &str, args: &[&'static str], working_dir: Option<&PathBuf>) -> Result<()> {
+ let mut cmd = Command::new("cargo");
+ let mut is_nightly_cmd = Command::new("cargo");
+ if let Some(dir) = working_dir {
+ cmd.current_dir(dir);
+ is_nightly_cmd.current_dir(dir);
+ }
+
+ let is_nightly_default = is_nightly_cmd
+ .arg("--version")
+ .output()
+ .map_err(|_| ())
+ .and_then(|o| String::from_utf8(o.stdout).map_err(|_| ()))
+ .unwrap_or_default()
+ .contains("-nightly");
+
+ if !is_nightly_default {
+ cmd.arg("+nightly");
+ }
+
+ let output = cmd
+ .arg(command)
+ .args(args)
+ .output()?;
+
+ if !output.status.success() {
+ // Dump the output streams produced by cargo into the stdout/stderr.
+ io::stdout().write_all(&output.stdout)?;
+ io::stderr().write_all(&output.stderr)?;
+ return Err(error::CommandError::BuildFailed)
+ }
+
+ Ok(())
+}
+
#[cfg(test)]
mod tests {
use std::path::PathBuf;
diff --git a/cli/src/main.rs b/cli/src/main.rs
index 05b79ad3289870714c541c52fe6c39ae2416fb89..4ba29e16e1725f19b86cf483483f7fce6e2d57a2 100644
--- a/cli/src/main.rs
+++ b/cli/src/main.rs
@@ -94,6 +94,9 @@ enum Command {
/// Builds the smart contract.
#[structopt(name = "build")]
Build {},
+ /// Generate abi artifacts
+ #[structopt(name = "generate-abi")]
+ GenerateAbi {},
/// Test the smart contract off-chain.
#[structopt(name = "test")]
Test {},
@@ -142,6 +145,7 @@ fn exec(cmd: Command) -> cmd::Result {
target_dir,
} => cmd::execute_new(*layer, name, target_dir.as_ref()),
Command::Build {} => cmd::execute_build(None),
+ Command::GenerateAbi {} => cmd::execute_generate_abi(None),
Command::Test {} => Err(CommandError::UnimplementedCommand),
Command::Deploy {
url,