sylvia/
into_response.rs

1use cosmwasm_std::{CosmosMsg, Empty, Response, StdError, StdResult, SubMsg};
2
3/// Trait converting `SubMsg` to one carrying another chain-custom message
4pub trait IntoMsg<C> {
5    fn into_msg(self) -> StdResult<SubMsg<C>>;
6}
7
8/// `SubMsg<Empty>` can be made into any `SubMsg<C>`
9impl<C> IntoMsg<C> for SubMsg<Empty> {
10    fn into_msg(self) -> StdResult<SubMsg<C>> {
11        let msg = match self.msg {
12            CosmosMsg::Wasm(wasm) => CosmosMsg::Wasm(wasm),
13            CosmosMsg::Bank(bank) => CosmosMsg::Bank(bank),
14            #[cfg(feature = "staking")]
15            CosmosMsg::Staking(staking) => CosmosMsg::Staking(staking),
16            #[cfg(feature = "staking")]
17            CosmosMsg::Distribution(distribution) => CosmosMsg::Distribution(distribution),
18            CosmosMsg::Custom(_) => Err(StdError::generic_err(
19                "Custom Empty message should not be sent",
20            ))?,
21            #[cfg(feature = "stargate")]
22            CosmosMsg::Ibc(ibc) => CosmosMsg::Ibc(ibc),
23            #[cfg(feature = "cosmwasm_2_0")]
24            CosmosMsg::Any(any) => CosmosMsg::Any(any),
25            #[cfg(feature = "stargate")]
26            CosmosMsg::Gov(msg) => CosmosMsg::Gov(msg),
27            _ => return Err(StdError::generic_err(format!(
28                "Unknown message variant: {:?}. Please make sure you are using up-to-date Sylvia version, and if so please issue this bug on the Sylvia repository.",
29                self
30            ))),
31        };
32
33        Ok(SubMsg {
34            msg,
35            id: self.id,
36            gas_limit: self.gas_limit,
37            reply_on: self.reply_on,
38            payload: self.payload,
39        })
40    }
41}
42
43pub trait IntoResponse<T> {
44    fn into_response(self) -> StdResult<Response<T>>;
45}
46
47impl<T> IntoResponse<T> for Response<Empty> {
48    fn into_response(self) -> StdResult<Response<T>> {
49        let messages: Vec<_> = self
50            .messages
51            .into_iter()
52            .map(|msg| msg.into_msg())
53            .collect::<StdResult<_>>()?;
54        let mut resp = Response::new()
55            .add_submessages(messages)
56            .add_events(self.events)
57            .add_attributes(self.attributes);
58        resp.data = self.data;
59
60        Ok(resp)
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use cosmwasm_std::{BankMsg, CosmosMsg, CustomMsg, Empty, Response, StdError};
67    use schemars::JsonSchema;
68    use serde::{Deserialize, Serialize};
69
70    use super::IntoResponse;
71
72    #[derive(Serialize, Deserialize, JsonSchema, Debug, Clone, PartialEq, Eq)]
73    struct MyMsg {}
74
75    impl CustomMsg for MyMsg {}
76
77    #[test]
78    fn into_custom() {
79        let resp = Response::<Empty>::default();
80        let _: Response<MyMsg> = resp.into_response().unwrap();
81
82        let mut resp = Response::<Empty>::default();
83        resp = resp.add_message(CosmosMsg::Bank(BankMsg::Send {
84            to_address: "some_address".to_owned(),
85            amount: vec![],
86        }));
87        let _: Response<MyMsg> = resp.into_response().unwrap();
88    }
89
90    #[test]
91    fn empty_custom_msg() {
92        let mut resp = Response::<Empty>::default();
93        resp = resp.add_message(CosmosMsg::Custom(Empty {}));
94
95        let err = IntoResponse::<MyMsg>::into_response(resp).unwrap_err();
96        assert_eq!(
97            err,
98            StdError::generic_err("Custom Empty message should not be sent")
99        );
100    }
101}