diff --git a/workspaces/src/operations.rs b/workspaces/src/operations.rs index 536cb840..c0c43cb8 100644 --- a/workspaces/src/operations.rs +++ b/workspaces/src/operations.rs @@ -102,6 +102,8 @@ impl<'a> Function<'a> { /// is most commonly constructed from [`Account::batch`] or [`Contract::batch`], /// where `receiver_id` is specified in the `Account::batch` while `Contract::id()` /// is used by default for `Contract::batch`. +/// +/// [`Contract::batch`]: crate::Contract::batch pub struct Transaction<'a> { client: &'a Client, signer: InMemorySigner, diff --git a/workspaces/src/result.rs b/workspaces/src/result.rs index 377101d5..c9975e17 100644 --- a/workspaces/src/result.rs +++ b/workspaces/src/result.rs @@ -17,7 +17,7 @@ pub type Result = core::result::Result; /// Execution related info as a result of performing a successful transaction /// execution on the network. This value can be converted into the returned /// value of the transaction via [`ExecutionSuccess::json`] or [`ExecutionSuccess::borsh`] -pub type ExecutionSuccess = ExecutionResult; +pub type ExecutionSuccess = ExecutionResult; /// Execution related info as a result of performing a failed transaction /// execution on the network. The related error message can be retrieved @@ -198,7 +198,7 @@ impl ExecutionFinalResult { match self.status { FinalExecutionStatus::SuccessValue(value) => Ok(ExecutionResult { total_gas_burnt: self.total_gas_burnt, - value: base64::encode(value), + value: Value::from_string(base64::encode(value)), details: self.details, }), FinalExecutionStatus::Failure(tx_error) => Err(ExecutionResult { @@ -293,25 +293,22 @@ impl ExecutionSuccess { /// execution result of this call. This conversion can fail if the structure of /// the internal state does not meet up with [`serde::de::DeserializeOwned`]'s /// requirements. - pub fn json(&self) -> Result { - let buf = self.raw_bytes()?; - serde_json::from_slice(&buf).map_err(|e| ErrorKind::DataConversion.custom(e)) + pub fn json(&self) -> Result { + self.value.json() } /// Deserialize an instance of type `T` from bytes sourced from the execution /// result. This conversion can fail if the structure of the internal state does /// not meet up with [`borsh::BorshDeserialize`]'s requirements. - pub fn borsh(&self) -> Result { - let buf = self.raw_bytes()?; - borsh::BorshDeserialize::try_from_slice(&buf) - .map_err(|e| ErrorKind::DataConversion.custom(e)) + pub fn borsh(&self) -> Result { + self.value.borsh() } /// Grab the underlying raw bytes returned from calling into a contract's function. /// If we want to deserialize these bytes into a rust datatype, use [`ExecutionResult::json`] /// or [`ExecutionResult::borsh`] instead. pub fn raw_bytes(&self) -> Result> { - base64::decode(&self.value).map_err(|e| ErrorKind::DataConversion.custom(e)) + self.value.raw_bytes() } } @@ -435,9 +432,9 @@ impl ExecutionOutcome { /// particular outcome has failed or not. pub fn into_result(self) -> Result { match self.status { - ExecutionStatusView::SuccessValue(value) => { - Ok(ValueOrReceiptId::Value(base64::encode(value))) - } + ExecutionStatusView::SuccessValue(value) => Ok(ValueOrReceiptId::Value( + Value::from_string(base64::encode(value)), + )), ExecutionStatusView::SuccessReceiptId(hash) => { Ok(ValueOrReceiptId::ReceiptId(CryptoHash(hash.0))) } @@ -450,14 +447,57 @@ impl ExecutionOutcome { } /// Value or ReceiptId from a successful execution. +#[derive(Debug)] pub enum ValueOrReceiptId { /// The final action succeeded and returned some value or an empty vec encoded in base64. - Value(String), + Value(Value), /// The final action of the receipt returned a promise or the signed transaction was converted /// to a receipt. Contains the receipt_id of the generated receipt. ReceiptId(CryptoHash), } +/// Value type returned from an [`ExecutionOutcome`] or receipt result. This value +/// can be converted into the underlying Rust datatype, or directly grab the raw +/// bytes associated to the value. +#[derive(Debug)] +pub struct Value { + repr: String, +} + +impl Value { + fn from_string(value: String) -> Self { + Self { repr: value } + } + + /// Deserialize an instance of type `T` from bytes of JSON text sourced from the + /// execution result of this call. This conversion can fail if the structure of + /// the internal state does not meet up with [`serde::de::DeserializeOwned`]'s + /// requirements. + pub fn json(&self) -> Result { + let buf = self.raw_bytes()?; + serde_json::from_slice(&buf).map_err(|e| ErrorKind::DataConversion.custom(e)) + } + + /// Deserialize an instance of type `T` from bytes sourced from the execution + /// result. This conversion can fail if the structure of the internal state does + /// not meet up with [`borsh::BorshDeserialize`]'s requirements. + pub fn borsh(&self) -> Result { + let buf = self.raw_bytes()?; + borsh::BorshDeserialize::try_from_slice(&buf) + .map_err(|e| ErrorKind::DataConversion.custom(e)) + } + + /// Grab the underlying raw bytes returned from calling into a contract's function. + /// If we want to deserialize these bytes into a rust datatype, use [`json`] + /// or [`borsh`] instead. + /// + /// [`json`]: Value::json + /// [`borsh`]: Value::borsh + pub fn raw_bytes(&self) -> Result> { + base64::decode(&self.repr).map_err(|e| ErrorKind::DataConversion.custom(e)) + } +} + impl From for ExecutionOutcome { fn from(view: ExecutionOutcomeWithIdView) -> Self { ExecutionOutcome {