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 119 120 121 122 123 124 125 126
use cosmwasm_schema::cw_serde;
use cosmwasm_std::{
to_json_binary, wasm_execute, Binary, CosmosMsg, Empty, QueryRequest, StdError, StdResult,
};
use polytone::callbacks::{Callback, ErrorResponse, ExecutionResponse};
use schemars::JsonSchema;
use crate::{
base::ExecuteMsg,
objects::{chain_name::ChainName, module::ModuleInfo},
};
/// CallbackInfo from modules, that is turned into an IbcResponseMsg by the ibc client
/// A callback can only be sent to itself
#[cosmwasm_schema::cw_serde]
// ANCHOR: callback-info
pub struct CallbackInfo {
/// Used to identify the callback that is sent (acts like the reply ID)
pub id: String,
/// Used to add information to the callback.
/// This is usually used to provide information to the ibc callback function for context
pub msg: Option<Binary>,
}
// ANCHOR_END: callback-info
impl CallbackInfo {
pub fn new(id: impl Into<String>, msg: Option<Binary>) -> Self {
Self { id: id.into(), msg }
}
}
/// IbcResponseMsg should be de/serialized under `IbcCallback()` variant in a ExecuteMsg
#[cosmwasm_schema::cw_serde]
// ANCHOR: response-msg
pub struct IbcResponseMsg {
/// The ID chosen by the caller in the `callback_info.id`
pub id: String,
/// The msg sent with the callback request.
/// This is usually used to provide information to the ibc callback function for context
pub msg: Option<Binary>,
pub result: CallbackResult,
}
// ANCHOR_END: response-msg
impl IbcResponseMsg {
/// serializes the message
pub fn into_json_binary(self) -> StdResult<Binary> {
let msg = ExecuteMsg::IbcCallback::<Empty, Empty>(self);
to_json_binary(&msg)
}
/// creates a cosmos_msg sending this struct to the named contract
pub fn into_cosmos_msg<T: Into<String>, C>(self, contract_addr: T) -> StdResult<CosmosMsg<C>>
where
C: Clone + std::fmt::Debug + PartialEq + JsonSchema,
{
Ok(wasm_execute(
contract_addr.into(),
&ExecuteMsg::IbcCallback::<Empty, Empty>(self),
vec![],
)?
.into())
}
}
#[cosmwasm_schema::cw_serde]
pub enum CallbackResult {
Query {
query: QueryRequest<Empty>,
// TODO: we allow only 1 query per tx, but return array here
result: Result<Vec<Binary>, ErrorResponse>,
},
Execute {
initiator_msg: Binary,
result: Result<ExecutionResponse, String>,
},
/// An error occured that could not be recovered from. The only
/// known way that this can occur is message handling running out
/// of gas, in which case the error will be `codespace: sdk, code:
/// 11`.
///
/// This error is not named becuase it could also occur due to a
/// panic or unhandled error during message processing. We don't
/// expect this to happen and have carefully written the code to
/// avoid it.
FatalError(String),
}
impl CallbackResult {
pub fn from_query(callback: Callback, query: QueryRequest<Empty>) -> Result<Self, StdError> {
match callback {
Callback::Query(q) => Ok(Self::Query { query, result: q }),
Callback::Execute(_) => Err(StdError::generic_err(
"Expected a query result, got an execute result",
)),
Callback::FatalError(e) => Ok(Self::FatalError(e)),
}
}
pub fn from_execute(callback: Callback, initiator_msg: Binary) -> Result<Self, StdError> {
match callback {
Callback::Query(_) => Err(StdError::generic_err(
"Expected an execution result, got a query result",
)),
Callback::Execute(e) => Ok(Self::Execute {
initiator_msg,
result: e,
}),
Callback::FatalError(e) => Ok(Self::FatalError(e)),
}
}
}
// ANCHOR: module_ibc_msg
#[cw_serde]
pub struct ModuleIbcMsg {
/// Remote chain identification
pub client_chain: ChainName,
/// Information about the module that called ibc action on this module
pub source_module: ModuleInfo,
/// The message sent by the module
pub msg: Binary,
}
// ANCHOR_END: module_ibc_msg