1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use std::fmt; use crate::{Binary, ContractResult}; use super::{CosmosMsg, Empty, Event}; /// Use this to define when the contract gets a response callback. /// If you only need it for errors or success you can select just those in order /// to save gas. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] #[serde(rename_all = "snake_case")] pub enum ReplyOn { /// Always perform a callback after SubMsg is processed Always, /// Only callback if SubMsg returned an error, no callback on success case Error, /// Only callback if SubMsg was successful, no callback on error case Success, /// Never make a callback - this is like the original CosmosMsg semantics Never, } /// A submessage that will guarantee a `reply` call on success or error, depending on /// the `reply_on` setting. If you do not need to process the result, use regular messages instead. /// /// Note: On error the submessage execution will revert any partial state changes due to this message, /// but not revert any state changes in the calling contract. If this is required, it must be done /// manually in the `reply` entry point. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct SubMsg<T = Empty> where T: Clone + fmt::Debug + PartialEq + JsonSchema, { /// An arbitrary ID chosen by the contract. /// This is typically used to match `Reply`s in the `reply` entry point to the submessage. pub id: u64, pub msg: CosmosMsg<T>, pub gas_limit: Option<u64>, pub reply_on: ReplyOn, } /// This is used for cases when we use ReplyOn::Never and the id doesn't matter pub const UNUSED_MSG_ID: u64 = 0; impl<T> SubMsg<T> where T: Clone + fmt::Debug + PartialEq + JsonSchema, { /// new creates a "fire and forget" message with the pre-0.14 semantics pub fn new<M: Into<CosmosMsg<T>>>(msg: M) -> Self { SubMsg { id: UNUSED_MSG_ID, msg: msg.into(), reply_on: ReplyOn::Never, gas_limit: None, } } /// create a `SubMsg` that will provide a `reply` with the given id if the message returns `Ok` pub fn reply_on_success<M: Into<CosmosMsg<T>>>(msg: M, id: u64) -> Self { Self::reply_on(msg.into(), id, ReplyOn::Success) } /// create a `SubMsg` that will provide a `reply` with the given id if the message returns `Err` pub fn reply_on_error<M: Into<CosmosMsg<T>>>(msg: M, id: u64) -> Self { Self::reply_on(msg.into(), id, ReplyOn::Error) } /// create a `SubMsg` that will always provide a `reply` with the given id pub fn reply_always<M: Into<CosmosMsg<T>>>(msg: M, id: u64) -> Self { Self::reply_on(msg.into(), id, ReplyOn::Always) } /// Add a gas limit to the message. /// /// ## Examples /// /// ``` /// # use cosmwasm_std::{coins, BankMsg, ReplyOn, SubMsg}; /// # let msg = BankMsg::Send { to_address: String::from("you"), amount: coins(1015, "earth") }; /// let sub_msg: SubMsg = SubMsg::reply_always(msg, 1234).with_gas_limit(60_000); /// assert_eq!(sub_msg.id, 1234); /// assert_eq!(sub_msg.gas_limit, Some(60_000)); /// assert_eq!(sub_msg.reply_on, ReplyOn::Always); /// ``` pub fn with_gas_limit(mut self, limit: u64) -> Self { self.gas_limit = Some(limit); self } fn reply_on(msg: CosmosMsg<T>, id: u64, reply_on: ReplyOn) -> Self { SubMsg { id, msg, reply_on, gas_limit: None, } } } /// The result object returned to `reply`. We always get the ID from the submessage /// back and then must handle success and error cases ourselves. #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct Reply { /// The ID that the contract set when emitting the `SubMsg`. /// Use this to identify which submessage triggered the `reply`. pub id: u64, pub result: ContractResult<SubMsgExecutionResponse>, } /// The information we get back from a successful sub-call, with full sdk events #[derive(Serialize, Deserialize, Clone, Debug, PartialEq, JsonSchema)] pub struct SubMsgExecutionResponse { pub events: Vec<Event>, pub data: Option<Binary>, }