Skip to content

Commit

Permalink
Update document in macro (#74)
Browse files Browse the repository at this point in the history
* Update document in macro
* Refactor ewasm_main and add example
  - add ewasm_auto_assert_eq!
  - add hello example
  - rename `#[ewas_main(unwrap)]` to `#[ewas_main(auto)]`
* Update README
* Add CI for hello example
  • Loading branch information
yanganto committed Jul 1, 2021
1 parent 089dcb4 commit 201096f
Show file tree
Hide file tree
Showing 18 changed files with 546 additions and 144 deletions.
32 changes: 32 additions & 0 deletions .github/workflows/hello_example.yml
@@ -0,0 +1,32 @@
name: CI

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]

workflow_dispatch:

jobs:
hello-example:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
with:
submodules: recursive

- name: Super-Linter
uses: github/super-linter@v3
env:
VALIDATE_ALL_CODEBASE: false
DEFAULT_BRANCH: main
VALIDATE_RUST_2018: true
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

- uses: cachix/install-nix-action@v13
with:
nix_path: nixpkgs=channel:nixos-21.05-small

- name: Default example test
run: nix-shell --run 'run-example-test hello'
1 change: 1 addition & 0 deletions Cargo.toml
Expand Up @@ -5,6 +5,7 @@ members = [
"sewup-derive",
]
exclude = [
"examples/hello-contract",
"examples/default-contract",
"examples/erc20-contract",
"examples/kv-contract",
Expand Down
75 changes: 68 additions & 7 deletions README.md
Expand Up @@ -5,7 +5,7 @@
[![Generic badge](https://img.shields.io/badge/SewUpDoc-main-green.svg)](https://second-state.github.io/SewUp/sewup/)
[![Generic badge](https://img.shields.io/badge/SewUpDeriveDoc-main-green.svg)](https://second-state.github.io/SewUp/sewup_derive/)

**S**econdstate **EW**asm **U**tility **P**rogram, a library to help you sew up your Ethereum project with Rust and just like develop in a common backend.
**S**econdstate **EW**asm **U**tility **P**rogram, a library helps you sew up your Ethereum project with Rust and just like develop in a common backend.

## Slides
| Date | Event | Slides |
Expand All @@ -14,19 +14,80 @@
| 2021/06/19 | Rust meetup (Beijing) | [v0.0.1-pre](https://slides.com/yanganto/sewup) |

## Usage
Add the `sewup` with the feature and the `sewup-derive` into Cargo.toml, and setup lib section as following, then you are ready to build contract with sewup.
Add `sewup` with the features and the `sewup-derive` into Cargo.toml, and setup other sections
as following, then you are ready to build contract with sewup.

Beside, we suggest you using `anyhow` to handle your result and error, but not limited to,
if you want to use other error crate please checkout `#[ewasm_main(rusty)]` and learn more.

```toml
[package]
name = "hello-contract"

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

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

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"
```
Besides, you can learn more from [examples/kv-contract](./examples/kv-contract), [examples/default-contract](./examples/default-contract), [examples/rusty-contract](./examples/rusty-contract) in the examples folder.
Place [.carggo/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_fn, ewasm_fn_sig, ewasm_main, ewasm_test};

#[ewasm_fn]
fn hello() -> Result<String> {
Ok("hello world".to_string())
}

#[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());
}
}
```

Run `cargo build --release --target=wasm32-unknown-unknown`, then the contract will build in `target/wasm32-unknown-unknown/release/*.wasm`
Besides, you also can easily run test with `cargo test`, the ewasm contract automatically test with [WasmEdge](https://github.com/WasmEdge/WasmEdge).
Furthermore, you can learn more from other examples in the [example](./examples/) folder.

## Development
The workspace have several project, the contract project should build with target `wasm32-unknown-unknown` and the flag `-Clink-arg=--export-table`.
After placing the `.wasm` output into [/resources/test](./resources/test), you can run `cargo test -p sewup --features=kv` to check on the test for kv features.
The workspace have several project, the contract project should build with target
`wasm32-unknown-unknown` and the flag `-C link-arg=--export-table`.

You can run `cargo test` in each example to check on the test your modification.
It is easy to participate with help want issues and the good first issues.
1 change: 0 additions & 1 deletion examples/default-contract/Cargo.toml
Expand Up @@ -12,7 +12,6 @@ crate-type = ["cdylib"]
[dependencies]
sewup ={ version = "0.0.3", path = "../../sewup" }
sewup-derive = { version = "0.0.3", path = "../../sewup-derive" }
ewasm_api = { version = "0.11.0", default-features = false, features = ["std", "qimalloc"], package = "ss_ewasm_api" }
anyhow = "1.0.40"
thiserror = "1.0.24"
serde = "1.0"
Expand Down
2 changes: 1 addition & 1 deletion examples/default-contract/src/errors.rs
Expand Up @@ -4,6 +4,6 @@ use thiserror::Error;
pub enum Error {
#[error("not trust input")]
NotTrustedInput,
#[error("unknow handler")]
#[error("unknown handler")]
UnknownHandle,
}
5 changes: 3 additions & 2 deletions examples/default-contract/src/lib.rs
Expand Up @@ -2,7 +2,7 @@ use anyhow::Result;
use serde_derive::{Deserialize, Serialize};

use sewup::primitives::Contract;
use sewup_derive::{ewasm_fn, ewasm_main, ewasm_test, fn_sig, input_from};
use sewup_derive::{ewasm_fn, ewasm_fn_sig, ewasm_input_from, ewasm_main, ewasm_test};

mod errors;
use errors::Error;
Expand All @@ -25,7 +25,7 @@ fn check_input_object(s: SimpleStruct) -> Result<()> {
fn main() -> Result<()> {
let contract = Contract::new()?;
match contract.get_function_selector()? {
fn_sig!(check_input_object) => input_from!(contract, check_input_object)?,
ewasm_fn_sig!(check_input_object) => ewasm_input_from!(contract, check_input_object)?,
_ => return Err(Error::UnknownHandle.into()),
};

Expand All @@ -35,6 +35,7 @@ fn main() -> Result<()> {
#[ewasm_test]
mod tests {
use super::*;
use sewup_derive::{ewasm_assert_eq, ewasm_assert_ok, ewasm_err_output};

#[ewasm_test]
fn test_execute_basic_operations() {
Expand Down
2 changes: 0 additions & 2 deletions examples/erc20-contract/Cargo.toml
Expand Up @@ -13,8 +13,6 @@ crate-type = ["cdylib"]
sewup ={ version = "0.0.3", path = "../../sewup", features = [ "token" ] }
sewup-derive = { version = "0.0.3", path = "../../sewup-derive" }
anyhow = "1.0.40"

[target.'cfg(target_arch = "wasm32")'.dependencies]
ewasm_api = { version = "0.11.0", default-features = false, features = ["std", "qimalloc"], package = "ss_ewasm_api" }

[dev-dependencies]
Expand Down
17 changes: 9 additions & 8 deletions examples/erc20-contract/src/token.rs
Expand Up @@ -9,7 +9,7 @@ use sewup::token::{
},
helpers::{copy_into_address, copy_into_array, copy_into_storage_value},
};
use sewup_derive::{ewasm_assert_eq, ewasm_fn, ewasm_main, ewasm_test, fn_sig};
use sewup_derive::{ewasm_fn, ewasm_fn_sig, ewasm_main, ewasm_test};

#[cfg(target_arch = "wasm32")]
use ewasm_api::types::*;
Expand Down Expand Up @@ -102,16 +102,16 @@ fn mint(contract: &Contract) {
fn main() -> Result<()> {
let contract = Contract::new()?;
match contract.get_function_selector()? {
fn_sig!(do_balance) => do_balance(&contract),
fn_sig!(do_transfer) => do_transfer(&contract),
ewasm_fn_sig!(do_balance) => do_balance(&contract),
ewasm_fn_sig!(do_transfer) => do_transfer(&contract),
NAME_SIG => name(),
SYMBOL_SIG => symbol("ETD"),
DECIMALS_SIG => decimals(),
TOTAL_SUPPLY_SIG => total_supply(),
fn_sig!(approve) => approve(&contract),
fn_sig!(allowance) => allowance(&contract),
fn_sig!(transfer_from) => transfer_from(&contract),
fn_sig!(mint) => mint(&contract),
ewasm_fn_sig!(approve) => approve(&contract),
ewasm_fn_sig!(allowance) => allowance(&contract),
ewasm_fn_sig!(transfer_from) => transfer_from(&contract),
ewasm_fn_sig!(mint) => mint(&contract),
_ => (),
};
Ok(())
Expand All @@ -120,7 +120,8 @@ fn main() -> Result<()> {
#[ewasm_test]
mod tests {
use super::*;
use hex_literal::*;
use hex_literal::hex;
use sewup_derive::ewasm_assert_eq;

#[ewasm_test]
fn test_execute_basic_operations() {
Expand Down
2 changes: 2 additions & 0 deletions examples/hello-contract/.cargo/config
@@ -0,0 +1,2 @@
[target.'cfg(target_arch="wasm32")']
rustflags = ["-C", "link-arg=--export-table"]
25 changes: 25 additions & 0 deletions examples/hello-contract/Cargo.toml
@@ -0,0 +1,25 @@
[package]
name = "hello-contract"
version = "0.1.0"
authors = ["Antonio Yang <yanganto@gmail.com>"]
edition = "2018"
description = "The example contract using sewup default feature"

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

[dependencies]
sewup ={ version = "0.0.3", path = "../../sewup" }
sewup-derive = { version = "0.0.3", path = "../../sewup-derive" }
anyhow = "1.0.40"

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

[profile.release.package.hello-contract]
incremental = false
opt-level = "z"
35 changes: 35 additions & 0 deletions examples/hello-contract/src/lib.rs
@@ -0,0 +1,35 @@
use anyhow::Result;

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

#[ewasm_fn]
fn hello() -> Result<String> {
Ok("hello world".to_string())
}

#[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_assert_eq, ewasm_auto_assert_eq, ewasm_output_from};

#[ewasm_test]
fn test_get_greeting() {
ewasm_assert_eq!(
hello(),
vec![11, 0, 0, 0, 0, 0, 0, 0, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]
);
ewasm_assert_eq!(hello(), ewasm_output_from!("hello world".to_string()));
ewasm_auto_assert_eq!(hello(), "hello world".to_string());
}
}
1 change: 0 additions & 1 deletion examples/kv-contract/Cargo.toml
Expand Up @@ -12,7 +12,6 @@ crate-type = ["cdylib"]
[dependencies]
sewup ={ version = "0.0.3", path = "../../sewup", features = [ "kv" ] }
sewup-derive = { version = "0.0.3", path = "../../sewup-derive" }
ewasm_api = { version = "0.11.0", default-features = false, features = ["std", "qimalloc"], package = "ss_ewasm_api" }
anyhow = "1.0.40"
thiserror = "1.0.24"
serde = "1.0"
Expand Down
8 changes: 4 additions & 4 deletions examples/kv-contract/src/errors.rs
Expand Up @@ -3,20 +3,20 @@ use thiserror::Error;

#[derive(Error, Debug, PartialEq)]
pub enum KVError {
#[error("the db version `{0}` is unexpect.")]
#[error("the DB version `{0}` is unexpected.")]
UnexpectVersion(u8),
#[error("features are compatible, current features are: `{0:?}`.")]
IncompatibleFeatures(Vec<Feature>),
#[error("current db size is `{0}`.")]
#[error("current DB size is `{0}`.")]
UnexpectedDBSize(u32),
#[error("current bucket are: `{0:?}.`")]
IncorrectBuckets(Vec<String>),
#[error("bucket error: `{0}.`")]
BucketError(String),
#[error("current value is `{0}.`")]
ValueError(String),
#[error("ValueNotFound")]
#[error("value not found")]
ValueNotFound,
#[error("unknow handler")]
#[error("unknown handler")]
UnknownHandle,
}
21 changes: 11 additions & 10 deletions examples/kv-contract/src/lib.rs
Expand Up @@ -4,7 +4,7 @@ use serde_derive::{Deserialize, Serialize};
use sewup::kv::{Feature, Store};
use sewup::primitives::Contract;
use sewup::types::{Raw, Row};
use sewup_derive::{ewasm_fn, ewasm_main, ewasm_test, fn_sig, Value};
use sewup_derive::{ewasm_fn, ewasm_fn_sig, ewasm_main, ewasm_test, Value};

mod errors;
use errors::KVError;
Expand Down Expand Up @@ -185,23 +185,23 @@ fn main() -> Result<()> {
let contract = Contract::new()?;

match contract.get_function_selector()? {
fn_sig!(empty_commit) => empty_commit()?,
fn_sig!(check_version_and_features) => {
ewasm_fn_sig!(empty_commit) => empty_commit()?,
ewasm_fn_sig!(check_version_and_features) => {
check_version_and_features(1, vec![Feature::Default])?
}
fn_sig!(check_empty_storage_size) => check_empty_storage_size(EMPTY_DB_SIZE)?,
fn_sig!(add_buckets) => add_buckets()?,
fn_sig!(check_buckets) => {
ewasm_fn_sig!(check_empty_storage_size) => check_empty_storage_size(EMPTY_DB_SIZE)?,
ewasm_fn_sig!(add_buckets) => add_buckets()?,
ewasm_fn_sig!(check_buckets) => {
check_buckets(vec!["bucket1".to_string(), "bucket2".to_string()])?
}
fn_sig!(drop_bucket_than_check) => {
ewasm_fn_sig!(drop_bucket_than_check) => {
drop_bucket_than_check("bucket1", vec!["bucket2".to_string()])?
}

// Following handler is for other test
fn_sig!(new_bucket_with_specific_struct) => new_bucket_with_specific_struct()?,
fn_sig!(check_objects_in_bucket) => check_objects_in_bucket()?,
fn_sig!(delete_object_in_bucket) => delete_object_in_bucket()?,
ewasm_fn_sig!(new_bucket_with_specific_struct) => new_bucket_with_specific_struct()?,
ewasm_fn_sig!(check_objects_in_bucket) => check_objects_in_bucket()?,
ewasm_fn_sig!(delete_object_in_bucket) => delete_object_in_bucket()?,
_ => return Err(KVError::UnknownHandle.into()),
};

Expand All @@ -211,6 +211,7 @@ fn main() -> Result<()> {
#[ewasm_test]
mod tests {
use super::*;
use sewup_derive::{ewasm_assert_eq, ewasm_assert_ok, ewasm_err_output};

#[ewasm_test]
fn test_execute_storage_operations() {
Expand Down
1 change: 0 additions & 1 deletion examples/rusty-contract/Cargo.toml
Expand Up @@ -12,7 +12,6 @@ crate-type = ["cdylib"]
[dependencies]
sewup ={ version = "0.0.3", path = "../../sewup" }
sewup-derive = { version = "0.0.3", path = "../../sewup-derive" }
ewasm_api = { version = "0.11.0", default-features = false, features = ["std", "qimalloc"], package = "ss_ewasm_api" }
anyhow = "1.0.40"
thiserror = "1.0.24"
serde = "1.0"
Expand Down

0 comments on commit 201096f

Please sign in to comment.