From eada0d52da65bf00730eba605084256bc33bfe8f Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 20 Feb 2026 14:24:10 -0800 Subject: [PATCH 1/3] Auto-convert numbers to strings when type is string while using `contract invoke`. --- cmd/crates/soroban-spec-tools/src/lib.rs | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index e33f7a493..b74031985 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -291,6 +291,9 @@ impl Spec { ScType::Bytes | ScType::BytesN(_) if matches!(val, Value::Number(_)) => { Ok(Value::String(s.to_owned())) } + ScType::String if !matches!(val, Value::String(_)) => { + Ok(Value::String(s.to_owned())) + } ScType::Timepoint | ScType::Duration => { // timepoint and duration both expect a JSON object with the value // being the u64 number as a string, and key being the type name @@ -2365,4 +2368,38 @@ mod tests { let result = spec.find_events(); assert!(result.is_err()); } + + fn sc_string(s: &str) -> ScVal { + ScVal::String(ScString(s.try_into().unwrap())) + } + + #[test] + fn test_string_from_number() { + let parsed = from_string_primitive("5", &ScType::String).unwrap(); + assert_eq!(parsed, sc_string("5")); + } + + #[test] + fn test_string_from_bool() { + let parsed = from_string_primitive("true", &ScType::String).unwrap(); + assert_eq!(parsed, sc_string("true")); + } + + #[test] + fn test_string_from_bare_word() { + let parsed = from_string_primitive("hello", &ScType::String).unwrap(); + assert_eq!(parsed, sc_string("hello")); + } + + #[test] + fn test_string_from_json_quoted_string() { + let parsed = from_string_primitive(r#""hello""#, &ScType::String).unwrap(); + assert_eq!(parsed, sc_string("hello")); + } + + #[test] + fn test_string_from_json_quoted_number_string() { + let parsed = from_string_primitive(r#""5""#, &ScType::String).unwrap(); + assert_eq!(parsed, sc_string("5")); + } } From fdaa853785c8a371718985903f002150ee36b58c Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 20 Feb 2026 14:31:32 -0800 Subject: [PATCH 2/3] Address pr feedback. --- cmd/crates/soroban-spec-tools/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index b74031985..83f06a607 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -291,7 +291,7 @@ impl Spec { ScType::Bytes | ScType::BytesN(_) if matches!(val, Value::Number(_)) => { Ok(Value::String(s.to_owned())) } - ScType::String if !matches!(val, Value::String(_)) => { + ScType::String if matches!(val, Value::Number(_) | Value::Bool(_)) => { Ok(Value::String(s.to_owned())) } ScType::Timepoint | ScType::Duration => { From f740f02e8fbf78cc5cef706df8d7704857ae1bda Mon Sep 17 00:00:00 2001 From: Nando Vieira Date: Fri, 20 Feb 2026 14:35:54 -0800 Subject: [PATCH 3/3] Actually, convert everything to string. --- cmd/crates/soroban-spec-tools/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/crates/soroban-spec-tools/src/lib.rs b/cmd/crates/soroban-spec-tools/src/lib.rs index 83f06a607..b74031985 100644 --- a/cmd/crates/soroban-spec-tools/src/lib.rs +++ b/cmd/crates/soroban-spec-tools/src/lib.rs @@ -291,7 +291,7 @@ impl Spec { ScType::Bytes | ScType::BytesN(_) if matches!(val, Value::Number(_)) => { Ok(Value::String(s.to_owned())) } - ScType::String if matches!(val, Value::Number(_) | Value::Bool(_)) => { + ScType::String if !matches!(val, Value::String(_)) => { Ok(Value::String(s.to_owned())) } ScType::Timepoint | ScType::Duration => {