use super::Data;
use crate::{
proto::{self, traits::Message, Any},
tx::Msg,
ErrorReport, Result,
};
use eyre::eyre;
use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MsgData {
pub msg_type: String,
pub data: Vec<u8>,
}
impl MsgData {
pub fn try_decode_as<M: Msg>(&self) -> Result<M> {
M::Proto::decode(&*self.data)?.try_into()
}
}
impl Msg for MsgData {
type Proto = proto::cosmos::base::abci::v1beta1::MsgData;
}
impl TryFrom<proto::cosmos::base::abci::v1beta1::MsgData> for MsgData {
type Error = ErrorReport;
fn try_from(proto: proto::cosmos::base::abci::v1beta1::MsgData) -> Result<MsgData> {
Ok(MsgData {
msg_type: proto.msg_type,
data: proto.data,
})
}
}
impl From<MsgData> for proto::cosmos::base::abci::v1beta1::MsgData {
fn from(msg_data: MsgData) -> Self {
proto::cosmos::base::abci::v1beta1::MsgData {
msg_type: msg_data.msg_type,
data: msg_data.data,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct MsgResponse {
pub type_url: String,
pub value: Vec<u8>,
}
impl MsgResponse {
pub fn try_decode_as<M: Msg>(&self) -> Result<M> {
M::Proto::decode(&*self.value)?.try_into()
}
}
impl From<Any> for MsgResponse {
fn from(any: Any) -> Self {
MsgResponse {
type_url: any.type_url,
value: any.value,
}
}
}
impl From<MsgResponse> for Any {
fn from(msg_response: MsgResponse) -> Self {
Any {
type_url: msg_response.type_url,
value: msg_response.value,
}
}
}
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Serialize, Deserialize)]
pub struct TxMsgData {
pub data: Vec<MsgData>,
pub msg_responses: Vec<MsgResponse>,
}
impl TryFrom<Data> for TxMsgData {
type Error = ErrorReport;
fn try_from(data: Data) -> Result<TxMsgData> {
proto::cosmos::base::abci::v1beta1::TxMsgData::decode(data.as_ref())?.try_into()
}
}
impl Msg for TxMsgData {
type Proto = proto::cosmos::base::abci::v1beta1::TxMsgData;
}
impl TryFrom<proto::cosmos::base::abci::v1beta1::TxMsgData> for TxMsgData {
type Error = ErrorReport;
#[allow(deprecated)]
fn try_from(proto: proto::cosmos::base::abci::v1beta1::TxMsgData) -> Result<TxMsgData> {
if !proto.msg_responses.is_empty() && !proto.data.is_empty() {
return Err(eyre!(
"TxMsgData: both msg_responses and data fields are populated"
));
}
Ok(TxMsgData {
data: proto
.data
.into_iter()
.map(TryFrom::try_from)
.collect::<Result<_, _>>()?,
msg_responses: proto.msg_responses.into_iter().map(Into::into).collect(),
})
}
}
impl From<TxMsgData> for proto::cosmos::base::abci::v1beta1::TxMsgData {
#[allow(deprecated)]
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: tx_msg_data
.msg_responses
.into_iter()
.map(Into::into)
.collect(),
}
}
}