From 048f8e7d0f54e3ad3ceeaa0f34692db459daba79 Mon Sep 17 00:00:00 2001 From: Daniel Gushchyan <39884512+dangush@users.noreply.github.com> Date: Fri, 9 Aug 2024 08:52:06 -0700 Subject: [PATCH] feat: cli contract build (#138) --- cli/src/cli.rs | 5 ++-- cli/src/error.rs | 2 +- cli/src/handler.rs | 2 ++ cli/src/handler/contract_build.rs | 45 ++++++++++++++++++++++++++++++ cli/src/request.rs | 14 ++++++++-- cli/src/request/contract_build.rs | 14 ++++++++++ cli/src/response.rs | 6 ++-- cli/src/response/contract_build.rs | 12 ++++++++ 8 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 cli/src/handler/contract_build.rs create mode 100644 cli/src/request/contract_build.rs create mode 100644 cli/src/response/contract_build.rs diff --git a/cli/src/cli.rs b/cli/src/cli.rs index e454296..5d70505 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -48,6 +48,7 @@ pub enum Command { #[clap(long, default_value = "quartz_app")] name: String, }, + /// Perform handshake Handshake { /// path to create & init a Quartz app, defaults to current path if unspecified #[arg(short, long, value_parser = wasmaddr_to_id)] @@ -72,7 +73,7 @@ pub enum Command { #[clap(long)] app_dir: Option, }, - /// Create an empty Quartz app from a template + /// Subcommands for handling the Quartz app contract Contract { #[command(subcommand)] contract_command: ContractCommand, @@ -88,7 +89,7 @@ pub enum Command { pub enum ContractCommand { Build { #[clap(long)] - path: Option, + manifest_path: PathBuf, }, Deploy { /// Json-formatted cosmwasm contract initialization message diff --git a/cli/src/error.rs b/cli/src/error.rs index ffe45ba..db68fd0 100644 --- a/cli/src/error.rs +++ b/cli/src/error.rs @@ -7,6 +7,6 @@ pub enum Error { PathNotDir(String), /// Specified file `{0}` does not exist PathNotFile(String), - /// {0} + /// unspecified error: {0} GenericErr(String), } diff --git a/cli/src/handler.rs b/cli/src/handler.rs index ed47a73..fc611b3 100644 --- a/cli/src/handler.rs +++ b/cli/src/handler.rs @@ -4,6 +4,7 @@ use crate::{error::Error, request::Request, response::Response, Config}; pub mod utils; // commands +pub mod contract_build; pub mod contract_deploy; pub mod enclave_build; pub mod handshake; @@ -26,6 +27,7 @@ impl Handler for Request { match self { Request::Init(request) => request.handle(config).await, Request::Handshake(request) => request.handle(config).await, + Request::ContractBuild(request) => request.handle(config).await, Request::ContractDeploy(request) => request.handle(config).await, Request::EnclaveBuild(request) => request.handle(config).await, } diff --git a/cli/src/handler/contract_build.rs b/cli/src/handler/contract_build.rs new file mode 100644 index 0000000..9ff3f78 --- /dev/null +++ b/cli/src/handler/contract_build.rs @@ -0,0 +1,45 @@ +use std::process::Command; + +use async_trait::async_trait; +use tracing::{debug, trace}; + +use crate::{ + error::Error, + handler::Handler, + request::contract_build::ContractBuildRequest, + response::{contract_build::ContractBuildResponse, Response}, + Config, +}; + +#[async_trait] +impl Handler for ContractBuildRequest { + type Error = Error; + type Response = Response; + + async fn handle(self, config: Config) -> Result { + let mut cargo = Command::new("cargo"); + let command = cargo + .arg("wasm") + .args(["--manifest-path", &self.manifest_path.display().to_string()]) + .env("RUSTFLAGS", "-C link-arg=-s"); + + if config.mock_sgx { + debug!("Building with mock-sgx enabled"); + command.arg("--features=mock-sgx"); + } + + trace!("🚧 Building contract binary ..."); + let status = command + .status() + .map_err(|e| Error::GenericErr(e.to_string()))?; + + if !status.success() { + return Err(Error::GenericErr(format!( + "Couldn't build contract. \n{:?}", + status + ))); + } + + Ok(ContractBuildResponse.into()) + } +} diff --git a/cli/src/request.rs b/cli/src/request.rs index e5d6b75..ab934e4 100644 --- a/cli/src/request.rs +++ b/cli/src/request.rs @@ -4,11 +4,12 @@ use crate::{ cli::{Command, ContractCommand, EnclaveCommand}, error::Error, request::{ - contract_deploy::ContractDeployRequest, enclave_build::EnclaveBuildRequest, - handshake::HandshakeRequest, init::InitRequest, + contract_build::ContractBuildRequest, contract_deploy::ContractDeployRequest, + enclave_build::EnclaveBuildRequest, handshake::HandshakeRequest, init::InitRequest, }, }; +pub mod contract_build; pub mod contract_deploy; pub mod enclave_build; pub mod handshake; @@ -18,6 +19,7 @@ pub mod init; pub enum Request { Init(InitRequest), Handshake(HandshakeRequest), + ContractBuild(ContractBuildRequest), ContractDeploy(ContractDeployRequest), EnclaveBuild(EnclaveBuildRequest), } @@ -94,7 +96,13 @@ impl TryFrom for Request { } .into()) } - ContractCommand::Build { path: _ } => todo!(), + ContractCommand::Build { manifest_path } => { + if !manifest_path.exists() { + return Err(Error::PathNotFile(manifest_path.display().to_string())); + } + + Ok(ContractBuildRequest { manifest_path }.into()) + } } } } diff --git a/cli/src/request/contract_build.rs b/cli/src/request/contract_build.rs new file mode 100644 index 0000000..23917be --- /dev/null +++ b/cli/src/request/contract_build.rs @@ -0,0 +1,14 @@ +use std::path::PathBuf; + +use crate::request::Request; + +#[derive(Clone, Debug)] +pub struct ContractBuildRequest { + pub manifest_path: PathBuf, +} + +impl From for Request { + fn from(request: ContractBuildRequest) -> Self { + Self::ContractBuild(request) + } +} diff --git a/cli/src/response.rs b/cli/src/response.rs index 69ded11..74db3a8 100644 --- a/cli/src/response.rs +++ b/cli/src/response.rs @@ -1,10 +1,11 @@ use serde::Serialize; use crate::response::{ - contract_deploy::ContractDeployResponse, enclave_build::EnclaveBuildResponse, - handshake::HandshakeResponse, init::InitResponse, + contract_build::ContractBuildResponse, contract_deploy::ContractDeployResponse, + enclave_build::EnclaveBuildResponse, handshake::HandshakeResponse, init::InitResponse, }; +pub mod contract_build; pub mod contract_deploy; pub mod enclave_build; pub mod handshake; @@ -14,6 +15,7 @@ pub mod init; pub enum Response { Init(InitResponse), Handshake(HandshakeResponse), + ContractBuild(ContractBuildResponse), ContractDeploy(ContractDeployResponse), EnclaveBuild(EnclaveBuildResponse), } diff --git a/cli/src/response/contract_build.rs b/cli/src/response/contract_build.rs new file mode 100644 index 0000000..7af325f --- /dev/null +++ b/cli/src/response/contract_build.rs @@ -0,0 +1,12 @@ +use serde::Serialize; + +use crate::response::Response; + +#[derive(Clone, Debug, Serialize)] +pub struct ContractBuildResponse; + +impl From for Response { + fn from(response: ContractBuildResponse) -> Self { + Self::ContractBuild(response) + } +}