Skip to content

Commit

Permalink
Init option for cargo-sewup (#201)
Browse files Browse the repository at this point in the history
* Implement init sub command for sewup cli
  • Loading branch information
yanganto committed Sep 22, 2021
1 parent e21c7eb commit 7e1981e
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 105 deletions.
88 changes: 1 addition & 87 deletions README.md
Expand Up @@ -34,93 +34,7 @@ please checkout `#[ewasm_main(auto)]` and `EwasmAny` or the example of rdb featu
how to write a flexible smart contract with ewasm.

### Develop
Following is the minimal setting to initial a sewup project.
```toml
# Cargo.toml
[package]
name = "hello-contract"

[lib]
path = "src/lib.rs"
crate-type = ["cdylib"]

[dependencies]
sewup = { version = "*", features = ['kv'] }
sewup-derive = { version = "*", features = ['kv'] }

anyhow = "1.0"

[profile.release]
incremental = false
panic = "abort"
lto = true
opt-level = "z"

[profile.release.package.hello-contract] # package name
incremental = false
opt-level = "z"

# Following features helps are used when building or testing a contract
[features]
constructor = [] # required
constructor-test = [] # required
```

```toml
# sewup.toml

# Following section including the parameters to deploy the contract
[deploy]
url = "http://localhost:8545" # url for rpc node
private = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # private key
address = "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" # account address
# gas = 5000000 # optional
# gas_price = 1 # optional

```
Place [.cargo/config](./examples/hello-contract/.cargo/config) file in your project to specify the flags for build.

Here is minimize example for writing a contract with sewup
```rust
// lib.rs
use anyhow::Result;

use sewup::primitives::Contract;
use sewup_derive::{ewasm_constructor, ewasm_fn, ewasm_fn_sig, ewasm_main, ewasm_test};

#[ewasm_constructor]
fn constructor() {
// do something you want when the contract deploy on chain
}

#[ewasm_fn]
fn hello() -> Result<String> {
let target = "world";
let greeting = "hello ".to_string() + sewup::ewasm_dbg!(target);
Ok(greeting)
}

#[ewasm_main(auto)]
fn main() -> Result<String> {
let contract = Contract::new()?;
let greeting = match contract.get_function_selector()? {
ewasm_fn_sig!(hello) => hello()?,
_ => panic!("unknown handle"),
};
Ok(greeting)
}

#[ewasm_test]
mod tests {
use super::*;
use sewup_derive::ewasm_auto_assert_eq;

#[ewasm_test]
fn test_get_greeting() {
ewasm_auto_assert_eq!(hello(), "hello world".to_string());
}
}
```
It is easy to setup your sewup project with `cargo-sewup init`, and you can learn more about the project configure with the [Deploy Guide](https://github.com/second-state/SewUp/wiki/Develop-Guide) wiki page.

### Interact
There are so many clients can interact with contract.
Expand Down
2 changes: 1 addition & 1 deletion SewUp.wiki
Submodule SewUp.wiki updated from 06eeee to 3e64cc
135 changes: 135 additions & 0 deletions cargo-sewup/src/init.rs
@@ -0,0 +1,135 @@
use std::path::Path;

use anyhow::{Context, Result};
use tokio::fs::{create_dir, write};

async fn init_gitignore() -> Result<()> {
write(".gitignore", b"/target\n/sewup.toml")
.await
.context("failed to init .gitignore")?;
Ok(())
}

async fn init_sewup_config() -> Result<()> {
write(
"sewup.toml",
r#"
[deploy]
url = "http://localhost:8545"
private = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
address = "0xXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
gas = 5000000
gas_price = 1"#,
)
.await
.context("failed to init sewup.toml")?;
Ok(())
}
async fn init_cargo_config() -> Result<()> {
create_dir(Path::new("./cargo")).await?;
write(
"./.cargo/config.rs",
r#"
[target.'cfg(target_arch="wasm32")']
rustflags = ["-C", "link-arg=--export-table"]"#,
)
.await?;
Ok(())
}

async fn init_cargo_toml() -> Result<()> {
let current_folder = std::env::current_dir()?;
let project_name = current_folder.file_name().unwrap().to_string_lossy();

write(
"Cargo.toml",
format!(
r#"
[package]
name = "{}"
version = "0.1.0"
edition = "2018"
[lib]
path = "src/lib.rs"
crate-type = ["cdylib"]
# See the hello example if you want to use a rust client
# https://github.com/second-state/SewUp/tree/main/examples/hello-contract
[dependencies]
sewup = "*"
sewup-derive = "*"
anyhow = "*"
[profile.release]
incremental = false
panic = "abort"
lto = true
opt-level = "z"
[profile.release.package.{}]
incremental = false
opt-level = "z"
[features]
constructor = []
constructor-test = []"#,
project_name, project_name
),
)
.await
.context("failed to init Cargo.toml")?;
Ok(())
}

async fn init_lib_file() -> Result<()> {
create_dir(Path::new("./src")).await?;
write(
"./src/lib.rs",
r#"
use sewup_derive::{ewasm_constructor, ewasm_fn, ewasm_fn_sig, ewasm_main, ewasm_test};
#[ewasm_constructor]
fn constructor() {}
#[ewasm_fn]
fn hello() -> anyhow::Result<String> {
Ok("hello world".to_string())
}
#[ewasm_main(auto)]
fn main() -> anyhow::Result<String> {
let contract = sewup::primitives::Contract::new()?;
let greeting = match contract.get_function_selector()? {
ewasm_fn_sig!(hello) => hello()?,
_ => panic!("unknown handle"),
};
Ok(greeting)
}
#[ewasm_test]
mod tests {
use super::*;
use sewup_derive::{ewasm_assert_eq, ewasm_auto_assert_eq, ewasm_output_from};
#[ewasm_test]
fn test_get_greeting() {
ewasm_auto_assert_eq!(hello(), "hello world".to_string());
}
}"#,
)
.await?;
Ok(())
}

pub async fn run() -> Result<()> {
tokio::try_join!(
init_gitignore(),
init_sewup_config(),
init_cargo_config(),
init_cargo_toml(),
init_lib_file()
)?;
Ok(())
}
50 changes: 33 additions & 17 deletions cargo-sewup/src/main.rs
Expand Up @@ -8,6 +8,7 @@ use tokio;
mod build;
mod deploy;
mod generate;
mod init;
mod inspect;

#[derive(StructOpt)]
Expand Down Expand Up @@ -36,33 +37,48 @@ struct Opt {
/// Generate ABI JSON if the handler is compaitabled with web3.js
#[structopt(short, long)]
generate_abi: bool,

/// `init` sub command to init project on current folder or on `--project_path`
sub_command: Option<String>,
}

#[tokio::main]
async fn main() -> Result<()> {
let opt = Opt::from_args();

if let Some(path) = opt.project_path {
env::set_current_dir(&Path::new(&path))?
let path = Path::new(&path);
if tokio::fs::metadata(path).await.is_err() {
tokio::fs::create_dir_all(path).await?;
}
env::set_current_dir(&path)?;
}
if opt.verbose {
println!("project : {}", env::current_dir()?.display());
}

return if let Some(inspect_file) = opt.inspect_file {
inspect::run(inspect_file).await
} else if opt.generate_abi {
generate::run().await
} else {
if opt.verbose {
println!("project : {}", env::current_dir()?.display());
if let Some(sub_command) = opt.sub_command {
if sub_command == "init" {
init::run().await
} else {
println!("Unknown sub command {:?}", sub_command);
Ok(())
}
} else {
return if let Some(inspect_file) = opt.inspect_file {
inspect::run(inspect_file).await
} else if opt.generate_abi {
generate::run().await
} else {
let contract_name = build::run(opt.debug).await?;

let contract_name = build::run(opt.debug).await?;

if !opt.build_only {
if opt.verbose {
println!("contract : {}", contract_name);
if !opt.build_only {
if opt.verbose {
println!("contract : {}", contract_name);
}
deploy::run(contract_name, opt.verbose, opt.debug).await?;
}
deploy::run(contract_name, opt.verbose, opt.debug).await?;
}
Ok(())
};
Ok(())
};
}
}

0 comments on commit 7e1981e

Please sign in to comment.