Skip to content

Commit 92942ee

Browse files
add the #[contract] macro
Signed-off-by: Valentyn Faychuk <valy@faychuk.com>
1 parent ac3c1ca commit 92942ee

11 files changed

Lines changed: 215 additions & 53 deletions

File tree

contract_samples/rust/Cargo.lock

Lines changed: 45 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

contract_samples/rust/Cargo.toml

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,6 @@
1-
[package]
2-
name = "amadeus-sdk"
3-
version = "0.1.0"
4-
edition = "2021"
5-
authors = ["Amadeus Team"]
6-
description = "Rust SDK for writing Amadeus smart contracts"
7-
license = "MIT"
8-
repository = "https://github.com/amadeusprotocol/node"
9-
10-
[lib]
11-
crate-type = ["cdylib", "rlib"]
12-
13-
[dependencies]
14-
dlmalloc = { version = "0.2", features = ["global"] }
1+
[workspace]
2+
resolver = "3"
3+
members = ["sdk", "sdk-macros"]
154

165
[profile.release]
176
opt-level = "z"
@@ -25,27 +14,3 @@ opt-level = "z"
2514

2615
[profile.dev]
2716
panic = "abort"
28-
29-
# WASM-specific build config
30-
[package.metadata.wasm-pack.profile.release]
31-
wasm-opt = false
32-
33-
[[example]]
34-
name = "counter"
35-
path = "examples/counter.rs"
36-
crate-type = ["cdylib"]
37-
38-
[[example]]
39-
name = "deposit"
40-
path = "examples/deposit.rs"
41-
crate-type = ["cdylib"]
42-
43-
[[example]]
44-
name = "coin"
45-
path = "examples/coin.rs"
46-
crate-type = ["cdylib"]
47-
48-
[[example]]
49-
name = "nft"
50-
path = "examples/nft.rs"
51-
crate-type = ["cdylib"]
Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,20 @@
11
#!/bin/bash
2-
32
set -e
43

5-
# Build each example
6-
cargo build --example counter --target wasm32-unknown-unknown --release
7-
cargo build --example deposit --target wasm32-unknown-unknown --release
8-
cargo build --example coin --target wasm32-unknown-unknown --release
9-
cargo build --example nft --target wasm32-unknown-unknown --release
4+
cargo build -p amadeus-sdk --example counter --target wasm32-unknown-unknown --release
5+
cargo build -p amadeus-sdk --example counter_macro --target wasm32-unknown-unknown --release
6+
cargo build -p amadeus-sdk --example deposit --target wasm32-unknown-unknown --release
7+
cargo build -p amadeus-sdk --example coin --target wasm32-unknown-unknown --release
8+
cargo build -p amadeus-sdk --example nft --target wasm32-unknown-unknown --release
9+
10+
wasm-opt -Oz --enable-bulk-memory target/wasm32-unknown-unknown/release/examples/counter.wasm -o target/wasm32-unknown-unknown/release/examples/counter_opt.wasm
11+
wasm-opt -Oz --enable-bulk-memory target/wasm32-unknown-unknown/release/examples/counter_macro.wasm -o target/wasm32-unknown-unknown/release/examples/counter_macro_opt.wasm
12+
wasm-opt -Oz --enable-bulk-memory target/wasm32-unknown-unknown/release/examples/deposit.wasm -o target/wasm32-unknown-unknown/release/examples/deposit_opt.wasm
13+
wasm-opt -Oz --enable-bulk-memory target/wasm32-unknown-unknown/release/examples/coin.wasm -o target/wasm32-unknown-unknown/release/examples/coin_opt.wasm
14+
wasm-opt -Oz --enable-bulk-memory target/wasm32-unknown-unknown/release/examples/nft.wasm -o target/wasm32-unknown-unknown/release/examples/nft_opt.wasm
1015

11-
# Validate each contract
12-
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/counter.wasm https://mainnet-rpc.ama.one/api/contract/validate
13-
echo ""
14-
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/deposit.wasm https://mainnet-rpc.ama.one/api/contract/validate
15-
echo ""
16-
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/coin.wasm https://mainnet-rpc.ama.one/api/contract/validate
17-
echo ""
18-
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/nft.wasm https://mainnet-rpc.ama.one/api/contract/validate
19-
echo ""
16+
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/counter_opt.wasm https://mainnet-rpc.ama.one/api/contract/validate
17+
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/counter_macro_opt.wasm https://mainnet-rpc.ama.one/api/contract/validate
18+
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/deposit_opt.wasm https://mainnet-rpc.ama.one/api/contract/validate
19+
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/coin_opt.wasm https://mainnet-rpc.ama.one/api/contract/validate
20+
curl -X POST -H "Content-Type: application/octet-stream" --data-binary @target/wasm32-unknown-unknown/release/examples/nft_opt.wasm https://mainnet-rpc.ama.one/api/contract/validate
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#![no_std]
2+
#![no_main]
3+
extern crate alloc;
4+
use amadeus_sdk::*;
5+
use alloc::string::String;
6+
use alloc::vec::Vec;
7+
8+
#[no_mangle]
9+
pub extern "C" fn init() {
10+
log("Init called during deployment of contract");
11+
kv_put("inited", "true");
12+
}
13+
14+
#[contract]
15+
fn get() -> i128 {
16+
kv_get("the_counter").unwrap_or(0)
17+
}
18+
19+
#[contract]
20+
fn increment(amount: Vec<u8>) -> String {
21+
kv_increment("the_counter", amount)
22+
}
23+
24+
#[contract]
25+
fn increment_another_counter(contract: Vec<u8>) -> Vec<u8> {
26+
let incr_by = 3i64;
27+
log("increment_another_counter");
28+
call!(contract.as_slice(), "increment", [incr_by])
29+
}
30+
31+
#[contract]
32+
fn set_message(msg: String) {
33+
kv_put("message", msg);
34+
}
35+
36+
#[contract]
37+
fn add_value(key: Vec<u8>, value: Vec<u8>) {
38+
kv_put(key, value);
39+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[package]
2+
name = "amadeus-sdk-macros"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[lib]
7+
proc-macro = true
8+
9+
[dependencies]
10+
syn = { version = "2.0", features = ["full"] }
11+
quote = "1.0"
12+
proc-macro2 = "1.0"
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
use proc_macro::TokenStream;
2+
use quote::quote;
3+
use syn::{parse_macro_input, FnArg, ItemFn, ReturnType, Type};
4+
5+
#[proc_macro_attribute]
6+
pub fn contract(_attr: TokenStream, item: TokenStream) -> TokenStream {
7+
let input = parse_macro_input!(item as ItemFn);
8+
let vis = &input.vis;
9+
let fn_name = &input.sig.ident;
10+
let impl_fn_name = syn::Ident::new(&format!("{}_impl", fn_name), fn_name.span());
11+
let inputs = &input.sig.inputs;
12+
let output = &input.sig.output;
13+
let block = &input.block;
14+
let attrs = &input.attrs;
15+
let has_return = !matches!(output, ReturnType::Default);
16+
17+
let mut param_count = 0;
18+
let mut wrapper_params = quote!{};
19+
let mut deserializations = quote!{};
20+
let mut call_args = quote!{};
21+
22+
for arg in inputs.iter() {
23+
if let FnArg::Typed(pat_type) = arg {
24+
let param_name = &pat_type.pat;
25+
let ptr_name = syn::Ident::new(&format!("arg{}_ptr", param_count), fn_name.span());
26+
27+
let deserialize_fn = match &*pat_type.ty {
28+
Type::Path(tp) if quote!(#tp).to_string().contains("String") => quote!(read_string),
29+
_ => quote!(read_bytes),
30+
};
31+
32+
if param_count > 0 {
33+
wrapper_params.extend(quote!(, #ptr_name: i32));
34+
call_args.extend(quote!(, #param_name));
35+
} else {
36+
wrapper_params.extend(quote!(#ptr_name: i32));
37+
call_args.extend(quote!(#param_name));
38+
}
39+
40+
deserializations.extend(quote! { let #param_name = #deserialize_fn(#ptr_name); });
41+
param_count += 1;
42+
}
43+
}
44+
45+
let wrapper_sig = if param_count == 0 {
46+
quote!(#[no_mangle] pub extern "C" fn #fn_name())
47+
} else {
48+
quote!(#[no_mangle] pub extern "C" fn #fn_name(#wrapper_params))
49+
};
50+
51+
let wrapper_call = if has_return {
52+
quote!(ret(#impl_fn_name(#call_args));)
53+
} else {
54+
quote!(#impl_fn_name(#call_args);)
55+
};
56+
57+
TokenStream::from(quote! {
58+
#wrapper_sig { #deserializations #wrapper_call }
59+
#(#attrs)* #vis fn #impl_fn_name(#inputs) #output #block
60+
})
61+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
[package]
2+
name = "amadeus-sdk"
3+
version = "0.1.0"
4+
edition = "2021"
5+
authors = ["Amadeus Team"]
6+
description = "Rust SDK for writing Amadeus smart contracts"
7+
license = "MIT"
8+
repository = "https://github.com/amadeusprotocol/node"
9+
10+
[lib]
11+
crate-type = ["cdylib", "rlib"]
12+
13+
[dependencies]
14+
dlmalloc = { version = "0.2", features = ["global"] }
15+
amadeus-sdk-macros = { path = "../sdk-macros" }
16+
17+
[package.metadata.wasm-pack.profile.release]
18+
wasm-opt = false
19+
20+
[[example]]
21+
name = "counter"
22+
path = "../examples/counter.rs"
23+
24+
[[example]]
25+
name = "deposit"
26+
path = "../examples/deposit.rs"
27+
28+
[[example]]
29+
name = "coin"
30+
path = "../examples/coin.rs"
31+
32+
[[example]]
33+
name = "nft"
34+
path = "../examples/nft.rs"
35+
36+
[[example]]
37+
name = "counter_macro"
38+
path = "../examples/counter_macro.rs"
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub mod encoding;
88
pub use context::*;
99
pub use storage::*;
1010
pub use encoding::*;
11+
pub use amadeus_sdk_macros::contract;
1112

1213
use core::panic::PanicInfo;
1314

0 commit comments

Comments
 (0)