From 4ffd8296cba4e9bff8816baf409c2a4faf4b51d4 Mon Sep 17 00:00:00 2001 From: Chad Ostrowski <221614+chadoh@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:52:52 -0400 Subject: [PATCH] fix: parse XDR Result to JSON; encode RawVal return types (#541) * fix: parse XDR Result to JSON The test here copies the logic of [the errors example](https://github.com/stellar/soroban-examples/blob/main/errors/src/lib.rs), showing that valid `Ok` results were not being correctly parsed to JSON. Co-authored-by: Willem Wyndham * fix(strval): encode RawVal return types --------- Co-authored-by: Willem Wyndham Co-authored-by: Paul Bellamy --- .../test-wasms/custom_type/src/lib.rs | 27 ++++++++++++- .../soroban-test/tests/it/custom_types.rs | 38 +++++++++++++++++++ cmd/soroban-cli/src/strval.rs | 8 +++- 3 files changed, 70 insertions(+), 3 deletions(-) diff --git a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs index 0b3ce9c2..938d9579 100644 --- a/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs +++ b/cmd/crates/soroban-test/tests/fixtures/test-wasms/custom_type/src/lib.rs @@ -1,7 +1,7 @@ #![no_std] use soroban_sdk::{ - contractimpl, contracttype, vec, Address, Bytes, BytesN, Env, Map, Set, String, Symbol, Vec, - I256, U256, + contracterror, contractimpl, contracttype, vec, Address, Bytes, BytesN, Env, Map, RawVal, Set, + String, Symbol, Vec, I256, U256, }; pub struct Contract; @@ -43,12 +43,35 @@ pub enum ComplexEnum { Void, } +#[contracterror] +#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[repr(u32)] +pub enum Error { + OhNo = 1, +} + #[contractimpl] impl Contract { pub fn hello(_env: Env, hello: Symbol) -> Symbol { hello } + pub fn void(_env: Env) { + // do nothing + } + + pub fn raw_val(_env: Env) -> RawVal { + RawVal::default() + } + + pub fn u32_fail_on_even(_env: Env, u32_: u32) -> Result { + if u32_ % 2 == 1 { + Ok(u32_) + } else { + Err(Error::OhNo) + } + } + pub fn u32_(_env: Env, u32_: u32) -> u32 { u32_ } diff --git a/cmd/crates/soroban-test/tests/it/custom_types.rs b/cmd/crates/soroban-test/tests/it/custom_types.rs index 80013d93..60185cb2 100644 --- a/cmd/crates/soroban-test/tests/it/custom_types.rs +++ b/cmd/crates/soroban-test/tests/it/custom_types.rs @@ -174,6 +174,44 @@ fn number_arg() { invoke_with_roundtrip("u32_", 42); } +#[test] +fn number_arg_return_ok() { + invoke(&TestEnv::default(), "u32_fail_on_even") + .arg("--u32_") + .arg("1") + .assert() + .success() + .stdout("1\n"); +} + +#[test] +fn number_arg_return_err() { + invoke(&TestEnv::default(), "u32_fail_on_even") + .arg("--u32_") + .arg("2") + .assert() + .success() + .stderr(predicates::str::contains("Status(ContractError(1))")); +} + +#[test] +fn void() { + invoke(&TestEnv::default(), "void") + .assert() + .success() + .stdout("\n") + .stderr(""); +} + +#[test] +fn raw_val() { + invoke(&TestEnv::default(), "raw_val") + .assert() + .success() + .stdout("null\n") + .stderr(""); +} + #[test] fn i32() { invoke_with_roundtrip("i32_", 42); diff --git a/cmd/soroban-cli/src/strval.rs b/cmd/soroban-cli/src/strval.rs index 573333c3..2162481a 100644 --- a/cmd/soroban-cli/src/strval.rs +++ b/cmd/soroban-cli/src/strval.rs @@ -438,7 +438,8 @@ impl Spec { /// May panic pub fn xdr_to_json(&self, val: &ScVal, output: &ScType) -> Result { Ok(match (val, output) { - (ScVal::Map(None) | ScVal::Vec(None), ScType::Option(_)) => Value::Null, + (ScVal::Void, ScType::Val) + | (ScVal::Map(None) | ScVal::Vec(None), ScType::Option(_)) => Value::Null, (ScVal::Bool(_), ScType::Bool) | (ScVal::Void, ScType::Void) | (ScVal::String(_), ScType::String) @@ -650,6 +651,11 @@ impl Spec { (ScVal::Address(v), ScType::Address) => sc_address_to_json(v), + (ok_val, ScType::Result(result_type)) => { + let ScSpecTypeResult { ok_type, .. } = result_type.as_ref(); + self.xdr_to_json(ok_val, ok_type)? + } + (x, y) => return Err(Error::InvalidPair(x.clone(), y.clone())), }) }