abstract_sdk/base/endpoints/
ibc_callback.rs

1use crate::base::features::ModuleIdentification;
2use crate::{base::Handler, AbstractSdkError};
3use abstract_std::ibc::IbcResponseMsg;
4use abstract_std::IBC_CLIENT;
5use cosmwasm_std::{Addr, Deps, DepsMut, Env, MessageInfo, Response, StdError};
6
7/// Trait for a contract's IBC callback ExecuteMsg variant.
8pub trait IbcCallbackEndpoint: Handler {
9    /// Queries the IBC Client address.
10    fn ibc_client_addr(&self, deps: Deps) -> Result<Addr, Self::Error>;
11
12    /// Handler for the `ExecuteMsg::IbcCallback()` variant.
13    fn ibc_callback(
14        self,
15        deps: DepsMut,
16        env: Env,
17        info: MessageInfo,
18        msg: IbcResponseMsg,
19    ) -> Result<Response, Self::Error> {
20        // Make sure module have ibc_client as dependency
21        if !self
22            .dependencies()
23            .iter()
24            .any(|static_dep| static_dep.id == IBC_CLIENT)
25        {
26            return Err(AbstractSdkError::Std(StdError::generic_err(format!(
27                "Ibc Client is not dependency of {}",
28                self.module_id()
29            )))
30            .into());
31        }
32
33        let ibc_client = self.ibc_client_addr(deps.as_ref())?;
34
35        if info.sender.ne(&ibc_client) {
36            return Err(AbstractSdkError::CallbackNotCalledByIbcClient {
37                caller: info.sender,
38                client_addr: ibc_client,
39                module: self.info().0.to_string(),
40            }
41            .into());
42        };
43        let ibc_callback_handler =
44            self.maybe_ibc_callback_handler()
45                .ok_or(AbstractSdkError::NoModuleIbcHandler(
46                    self.module_id().to_string(),
47                ))?;
48
49        ibc_callback_handler(deps, env, self, msg.callback, msg.result)
50    }
51}