diff --git a/cosmrs/.idea/workspace.xml b/cosmrs/.idea/workspace.xml new file mode 100644 index 00000000..5f0fccb3 --- /dev/null +++ b/cosmrs/.idea/workspace.xml @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + { + "associatedIndex": 7 +} + + + + { + "keyToString": { + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.rust.reset.selective.auto.import": "true", + "last_opened_file_path": "/Users/jedrzej/workspace/cosmos-rust-fork/cosmos-rust/cosmrs", + "node.js.detected.package.eslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true", + "org.rust.cargo.project.model.impl.CargoExternalSystemProjectAware.subscribe.first.balloon": "", + "org.rust.first.attach.projects": "true", + "settings.editor.selected.configurable": "language.rust.cargo.check" + } +} + + + + + + + + + 1718192228740 + + + + + + \ No newline at end of file diff --git a/cosmrs/src/abci.rs b/cosmrs/src/abci.rs index c26daa32..7bb967a5 100644 --- a/cosmrs/src/abci.rs +++ b/cosmrs/src/abci.rs @@ -5,7 +5,7 @@ mod msg_data; pub use self::{ gas_info::GasInfo, - msg_data::{MsgData, TxMsgData}, + msg_data::{MsgData, TxMsgData, MsgResponse}, }; /// Transaction data. diff --git a/cosmrs/src/abci/msg_data.rs b/cosmrs/src/abci/msg_data.rs index 22706546..17f4f1a2 100644 --- a/cosmrs/src/abci/msg_data.rs +++ b/cosmrs/src/abci/msg_data.rs @@ -1,13 +1,14 @@ use super::Data; use crate::{ - proto::{self, traits::Message}, + proto::{self, traits::Message, Any}, tx::Msg, ErrorReport, Result, }; use eyre::eyre; +use serde::{Deserialize, Serialize}; /// MsgData defines the data returned in a Result object during message execution. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct MsgData { /// Incoming message type that emitted this result data, for example `"/cosmos.bank.v1beta1.MsgSend"`. pub msg_type: String, @@ -50,13 +51,52 @@ impl From for proto::cosmos::base::abci::v1beta1::MsgData { } } +/// The messages responses of the TxMsgData. Corresponds to `Any` +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] +pub struct MsgResponse { + /// Response message type that emitted this result data, for example `"/cosmwasm.wasm.v1.MsgExecuteContractResponse"`. + pub type_url: String, + + /// Binary data emitted by this response. + pub value: Vec, +} + +impl MsgResponse { + /// Attempts to decode the `data` field of this result into the specified `Msg` type. + pub fn try_decode_as(&self) -> Result { + M::Proto::decode(&*self.value)?.try_into() + } +} + +impl From for MsgResponse { + fn from(any: Any) -> Self { + MsgResponse { + type_url: any.type_url, + value: any.value, + } + } +} + +impl From for Any { + fn from(msg_response: MsgResponse) -> Self { + Any { + type_url: msg_response.type_url, + value: msg_response.value, + } + } +} + /// TxMsgData defines a list of MsgData. A transaction will have a MsgData object for each message. -#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)] pub struct TxMsgData { /// Data emitted by the messages in a particular transaction. // Note: this field will be deprecated and not populated as of cosmos-sdk 0.46. // It will be superseded by `msg_responses` field of type Vec pub data: Vec, + + /// This field contains the Msg handler responses packed into Anys. + // Note: this field is an empty vec for chains running cosmos-sdk < 0.46. + pub msg_responses: Vec, } impl TryFrom for TxMsgData { @@ -76,9 +116,11 @@ impl TryFrom for TxMsgData { #[allow(deprecated)] fn try_from(proto: proto::cosmos::base::abci::v1beta1::TxMsgData) -> Result { - // TODO(tarcieri): parse `msg_responses` - if !proto.msg_responses.is_empty() { - return Err(eyre!("TxMsgData::msg_responses unsupported")); + // this case should be impossible as with the switch in cosmos-sdk 0.46 only one of those should contain any data + if !proto.msg_responses.is_empty() && !proto.data.is_empty() { + return Err(eyre!( + "TxMsgData: both msg_responses and data fields are populated" + )); } Ok(TxMsgData { @@ -87,6 +129,7 @@ impl TryFrom for TxMsgData { .into_iter() .map(TryFrom::try_from) .collect::>()?, + msg_responses: proto.msg_responses.into_iter().map(Into::into).collect(), }) } } @@ -96,7 +139,11 @@ impl From for proto::cosmos::base::abci::v1beta1::TxMsgData { fn from(tx_msg_data: TxMsgData) -> Self { proto::cosmos::base::abci::v1beta1::TxMsgData { data: tx_msg_data.data.into_iter().map(Into::into).collect(), - msg_responses: vec![], // TODO(tarcieri): serialize responses + msg_responses: tx_msg_data + .msg_responses + .into_iter() + .map(Into::into) + .collect(), } } }