diff --git a/data_structures/src/chain/mod.rs b/data_structures/src/chain/mod.rs index 9b1d8986c..cb22b32d6 100644 --- a/data_structures/src/chain/mod.rs +++ b/data_structures/src/chain/mod.rs @@ -15,7 +15,8 @@ use ethereum_types::U256; use failure::Fail; use futures::future::BoxFuture; use ordered_float::OrderedFloat; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; +use core::fmt::Display; use partial_struct::PartialStruct; use witnet_crypto::{ @@ -1604,6 +1605,10 @@ pub struct ValueTransferOutput { /// Address that will receive the value pub pkh: PublicKeyHash, /// Transferred value in nanowits + #[serde( + serialize_with = "u64_to_string", + deserialize_with = "number_from_string" + )] pub value: u64, /// The value attached to a time-locked output cannot be spent before the specified /// timestamp. That is, they cannot be used as an input in any transaction of a @@ -1611,6 +1616,39 @@ pub struct ValueTransferOutput { pub time_lock: u64, } +pub fn u64_to_string(val: &u64, serializer: S) -> Result +where + S: serde::Serializer, +{ + if serializer.is_human_readable() { + serializer.serialize_str(&val.to_string()) + } else { + serializer.serialize_u64(*val) + } +} + +pub fn number_from_string<'de, T, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, + T: FromStr + serde::Deserialize<'de>, + ::Err: Display, +{ + #[derive(Deserialize)] + #[serde(untagged)] + enum StringOrInt { + String(String), + Number(T), + } + if deserializer.is_human_readable() { + match StringOrInt::::deserialize(deserializer)? { + StringOrInt::String(s) => s.parse::().map_err(serde::de::Error::custom), + StringOrInt::Number(i) => Ok(i), + } + } else { + T::deserialize(deserializer) + } +} + impl ValueTransferOutput { #[inline] pub fn value(&self) -> u64 {