Skip to content

Commit f4340bc

Browse files
fix kv_exists usage and add testing
Signed-off-by: Valentyn Faychuk <[email protected]>
1 parent fa5ca6e commit f4340bc

File tree

9 files changed

+519
-51
lines changed

9 files changed

+519
-51
lines changed

contract_samples/rust/README.md

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,14 @@ cargo install amadeus-cli
2727
To build the wasm smart contracts, simply run the `./build_and_validate.sh`.
2828
The artifacts will be placed in `target/wasm32-unknown-unknown/release/examples`.
2929

30-
### Testing
30+
## Unit Testing
31+
32+
```bash
33+
cargo +nightly test --example showcase --features testing --no-default-features -- --nocapture --test-threads=1
34+
cargo expand -p amadeus-sdk --example showcase --target wasm32-unknown-unknown
35+
```
36+
37+
### Testnet Deployment
3138

3239
Make sure you have `amadeus-cli` installed.
3340
Follow the code snippet below to run each example on the testnet.
@@ -72,4 +79,15 @@ ama tx --sk wallet.sk $NFT_PK init '[]' --url https://testnet-rpc.ama.one
7279
ama tx --sk wallet.sk $NFT_PK claim '[]' --url https://testnet-rpc.ama.one
7380
ama tx --sk wallet.sk $NFT_PK view_nft '["AGENTIC", "1"]' --url https://testnet-rpc.ama.one
7481
ama tx --sk wallet.sk $NFT_PK claim '[]' --url https://testnet-rpc.ama.one
82+
83+
ama gen-sk showcase.sk
84+
export SHOWCASE_PK=$(ama get-pk --sk showcase.sk)
85+
ama tx --sk wallet.sk Coin transfer '[{"b58": "'$SHOWCASE_PK'"}, "2000000000", "AMA"]' --url https://testnet-rpc.ama.one
86+
ama deploy-tx --sk showcase.sk showcase.wasm --url https://testnet-rpc.ama.one
87+
ama tx --sk wallet.sk $SHOWCASE_PK increment_total_matches '[]' --url https://testnet-rpc.ama.one
88+
ama tx --sk wallet.sk $SHOWCASE_PK set_tournament_info '["World Cup", "1000000"]' --url https://testnet-rpc.ama.one
89+
ama tx --sk wallet.sk $SHOWCASE_PK record_win '["alice"]' --url https://testnet-rpc.ama.one
90+
ama tx --sk wallet.sk $SHOWCASE_PK record_win '["alice"]' --url https://testnet-rpc.ama.one
91+
ama tx --sk wallet.sk $SHOWCASE_PK get_player_wins '["alice"]' --url https://testnet-rpc.ama.one
92+
ama tx --sk wallet.sk $SHOWCASE_PK get_tournament_name '[]' --url https://testnet-rpc.ama.one
7593
```

contract_samples/rust/examples/showcase.rs

Lines changed: 100 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
1-
#![no_std]
2-
#![no_main]
1+
#![cfg_attr(not(any(test, feature = "testing")), no_std)]
2+
#![cfg_attr(not(any(test, feature = "testing")), no_main)]
3+
#![cfg_attr(any(test, feature = "testing"), feature(thread_local))]
34

45
extern crate alloc;
5-
use alloc::vec::Vec;
6+
7+
#[cfg(any(test, feature = "testing"))]
8+
extern crate std;
9+
610
use alloc::string::{String, ToString};
711
use amadeus_sdk::*;
812

@@ -36,8 +40,8 @@ impl Leaderboard {
3640
*self.total_matches += 1;
3741
}
3842

39-
pub fn get_total_matches(&self) -> Vec<u8> {
40-
(*self.total_matches).to_string().into_bytes()
43+
pub fn get_total_matches(&self) -> i32 {
44+
*self.total_matches
4145
}
4246

4347
pub fn record_match(&mut self, player: String, match_id: u64, score: u16, opponent: String) {
@@ -50,13 +54,13 @@ impl Leaderboard {
5054
*self.total_matches += 1;
5155
}
5256

53-
pub fn get_match_score(&self, player: String, match_id: u64) -> Vec<u8> {
57+
pub fn get_match_score(&self, player: String, match_id: u64) -> u16 {
5458
if let Some(matches) = self.players.get(player) {
5559
if let Some(m) = matches.get(match_id) {
56-
return (*m.score).to_string().into_bytes();
60+
return *m.score;
5761
}
5862
}
59-
"0".to_string().into_bytes()
63+
0
6064
}
6165

6266
pub fn get_match_opponent(&self, player: String, match_id: u64) -> String {
@@ -77,8 +81,8 @@ impl Leaderboard {
7781
(*self.tournament.name).clone()
7882
}
7983

80-
pub fn get_tournament_prize(&self) -> Vec<u8> {
81-
(*self.tournament.prize_pool).to_string().into_bytes()
84+
pub fn get_tournament_prize(&self) -> u64 {
85+
*self.tournament.prize_pool
8286
}
8387

8488
pub fn record_win(&mut self, player: String) {
@@ -89,15 +93,98 @@ impl Leaderboard {
8993
}
9094
}
9195

92-
pub fn get_player_wins(&self, player: String) -> Vec<u8> {
96+
pub fn get_player_wins(&self, player: String) -> u32 {
9397
if let Some(wins) = self.player_wins.get(&player) {
94-
(*wins).to_string().into_bytes()
98+
**wins
9599
} else {
96-
"0".to_string().into_bytes()
100+
0
97101
}
98102
}
99103

100104
pub fn set_player_wins(&mut self, player: String, wins: u32) {
101105
self.player_wins.insert(player, wins);
102106
}
103107
}
108+
109+
#[cfg(test)]
110+
mod tests {
111+
use super::*;
112+
use amadeus_sdk::testing::*;
113+
114+
#[test]
115+
fn test_increment_total_matches() {
116+
reset();
117+
let mut state = Leaderboard::with_prefix(Vec::new());
118+
state.increment_total_matches();
119+
state.flush();
120+
println!("\n{}\n", dump());
121+
let state2 = Leaderboard::with_prefix(Vec::new());
122+
assert_eq!(state2.get_total_matches(), 1);
123+
}
124+
125+
#[test]
126+
fn test_set_tournament_info() {
127+
reset();
128+
let mut state = Leaderboard::with_prefix(Vec::new());
129+
state.set_tournament_info("World Cup".to_string(), 1000000);
130+
state.flush();
131+
println!("\n{}\n", dump());
132+
let state2 = Leaderboard::with_prefix(Vec::new());
133+
assert_eq!(state2.get_tournament_name(), "World Cup");
134+
assert_eq!(state2.get_tournament_prize(), 1000000);
135+
}
136+
137+
#[test]
138+
fn test_record_win() {
139+
reset();
140+
let mut state = Leaderboard::with_prefix(Vec::new());
141+
state.record_win("alice".to_string());
142+
state.flush();
143+
println!("\n{}\n", dump());
144+
let state2 = Leaderboard::with_prefix(Vec::new());
145+
assert_eq!(state2.get_player_wins("alice".to_string()), 1);
146+
}
147+
148+
#[test]
149+
fn test_multiple_operations() {
150+
reset();
151+
152+
let mut state = Leaderboard::with_prefix(Vec::new());
153+
state.increment_total_matches();
154+
state.flush();
155+
println!("After increment_total_matches():\n{}\n", dump());
156+
157+
let mut state = Leaderboard::with_prefix(Vec::new());
158+
state.set_tournament_info("World Cup".to_string(), 1000000);
159+
state.flush();
160+
println!("After set_tournament_info():\n{}\n", dump());
161+
162+
let mut state = Leaderboard::with_prefix(Vec::new());
163+
state.record_win("alice".to_string());
164+
state.flush();
165+
println!("After record_win(alice):\n{}\n", dump());
166+
167+
let mut state = Leaderboard::with_prefix(Vec::new());
168+
state.record_win("alice".to_string());
169+
state.flush();
170+
println!("After record_win(alice) 2nd:\n{}\n", dump());
171+
172+
let mut state = Leaderboard::with_prefix(Vec::new());
173+
state.record_win("bob".to_string());
174+
state.flush();
175+
println!("After record_win(bob):\n{}\n", dump());
176+
177+
let mut state = Leaderboard::with_prefix(Vec::new());
178+
state.set_player_wins("charlie".to_string(), 5);
179+
state.flush();
180+
println!("After set_player_wins(charlie, 5):\n{}\n", dump());
181+
182+
let state = Leaderboard::with_prefix(Vec::new());
183+
assert_eq!(state.get_total_matches(), 1);
184+
assert_eq!(state.get_player_wins("alice".to_string()), 2);
185+
assert_eq!(state.get_player_wins("bob".to_string()), 1);
186+
assert_eq!(state.get_player_wins("charlie".to_string()), 5);
187+
assert_eq!(state.get_tournament_name(), "World Cup");
188+
assert_eq!(state.get_tournament_prize(), 1000000);
189+
}
190+
}

contract_samples/rust/sdk-macros/src/lib.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,13 +173,27 @@ fn handle_impl_block(impl_block: ItemImpl) -> TokenStream {
173173
quote!(#name(#(#call_args),*))
174174
};
175175

176+
let return_wrapper = if has_return {
177+
if let syn::ReturnType::Type(_, ret_type) = &method.sig.output {
178+
if is_integer_type(ret_type) {
179+
quote! { ret(result.to_string().into_bytes()); }
180+
} else {
181+
quote! { ret(result); }
182+
}
183+
} else {
184+
quote! { ret(result); }
185+
}
186+
} else {
187+
quote! {}
188+
};
189+
176190
let body = if has_return {
177191
quote! {
178192
#(#deserializations)*
179193
let mut state = <#self_ty as ContractState>::with_prefix(alloc::vec::Vec::new());
180194
let result = state.#call;
181195
state.flush();
182-
ret(result);
196+
#return_wrapper
183197
}
184198
} else {
185199
quote! {

contract_samples/rust/sdk/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,13 @@ repository = "https://github.com/amadeusprotocol/node"
1111
crate-type = ["cdylib", "rlib"]
1212

1313
[dependencies]
14-
dlmalloc = { version = "0.2", features = ["global"] }
1514
amadeus-sdk-macros = { path = "../sdk-macros" }
15+
dlmalloc = { version = "0.2", features = ["global"], optional = true }
16+
17+
[features]
18+
default = ["use-dlmalloc"]
19+
use-dlmalloc = ["dlmalloc"]
20+
testing = []
1621

1722
[package.metadata.wasm-pack.profile.release]
1823
wasm-opt = false

0 commit comments

Comments
 (0)