abstract_sdk/base/
handler.rs

1use abstract_std::objects::dependency::StaticDependency;
2use cosmwasm_std::Storage;
3use cw2::{ContractVersion, CONTRACT};
4
5use super::contract_base::{
6    AbstractContract, ExecuteHandlerFn, IbcCallbackHandlerFn, InstantiateHandlerFn,
7    MigrateHandlerFn, ModuleIbcHandlerFn, QueryHandlerFn, SudoHandlerFn,
8};
9use crate::{
10    base::{
11        contract_base::{ModuleId, ModuleMetadata, VersionString},
12        ReplyHandlerFn,
13    },
14    AbstractSdkError, AbstractSdkResult,
15};
16
17/// Accessor trait for an object that wraps an [`AbstractContract`].
18pub trait Handler
19where
20    Self: Sized + 'static,
21{
22    /// Error type for the contract
23    type Error: From<AbstractSdkError>;
24    /// Custom init message for the contract
25    type CustomInitMsg;
26    /// Custom execute message for the contract
27    type CustomExecMsg;
28    /// Custom query message for the contract
29    type CustomQueryMsg;
30    /// Custom migrate message for the contract
31    type CustomMigrateMsg;
32    /// Sudo message for the contract
33    type SudoMsg;
34
35    /// Returns the contract object.
36    fn contract(&self) -> &AbstractContract<Self, Self::Error>;
37
38    /// Returns the cw2 contract version.
39    fn stored_version(&self, store: &dyn Storage) -> AbstractSdkResult<ContractVersion> {
40        CONTRACT.load(store).map_err(Into::into)
41    }
42
43    /// Returns the static contract info.
44    fn info(&self) -> (ModuleId, VersionString, ModuleMetadata) {
45        let contract = self.contract();
46        contract.info
47    }
48
49    /// Returns the static contract dependencies.
50    fn dependencies(&self) -> &'static [StaticDependency] {
51        let contract = self.contract();
52        contract.dependencies
53    }
54    /// Get an execute handler if it exists.
55    fn maybe_execute_handler(
56        &self,
57    ) -> Option<ExecuteHandlerFn<Self, Self::CustomExecMsg, Self::Error>> {
58        let contract = self.contract();
59        contract.execute_handler
60    }
61    /// Get an execute handler or return an error.
62    fn execute_handler(
63        &self,
64    ) -> AbstractSdkResult<ExecuteHandlerFn<Self, Self::CustomExecMsg, Self::Error>> {
65        let Some(handler) = self.maybe_execute_handler() else {
66            return Err(AbstractSdkError::MissingHandler {
67                endpoint: "execution handler".to_string(),
68            });
69        };
70        Ok(handler)
71    }
72
73    /// Get a instantiate handler if it exists.
74    fn maybe_instantiate_handler(
75        &self,
76    ) -> Option<InstantiateHandlerFn<Self, Self::CustomInitMsg, Self::Error>> {
77        let contract = self.contract();
78        contract.instantiate_handler
79    }
80    /// Get an instantiate handler or return an error.
81    fn instantiate_handler(
82        &self,
83    ) -> AbstractSdkResult<InstantiateHandlerFn<Self, Self::CustomInitMsg, Self::Error>> {
84        let Some(handler) = self.maybe_instantiate_handler() else {
85            return Err(AbstractSdkError::MissingHandler {
86                endpoint: "instantiate".to_string(),
87            });
88        };
89        Ok(handler)
90    }
91
92    /// Get a query handler if it exists.
93    fn maybe_query_handler(
94        &self,
95    ) -> Option<QueryHandlerFn<Self, Self::CustomQueryMsg, Self::Error>> {
96        let contract = self.contract();
97        contract.query_handler
98    }
99    /// Get a query handler or return an error.
100    fn query_handler(
101        &self,
102    ) -> AbstractSdkResult<QueryHandlerFn<Self, Self::CustomQueryMsg, Self::Error>> {
103        let Some(handler) = self.maybe_query_handler() else {
104            return Err(AbstractSdkError::MissingHandler {
105                endpoint: "query".to_string(),
106            });
107        };
108        Ok(handler)
109    }
110
111    /// Get a migrate handler if it exists.
112    fn maybe_migrate_handler(
113        &self,
114    ) -> Option<MigrateHandlerFn<Self, Self::CustomMigrateMsg, Self::Error>> {
115        let contract = self.contract();
116        contract.migrate_handler
117    }
118    /// Get a migrate handler or return an error.
119    fn migrate_handler(
120        &self,
121    ) -> AbstractSdkResult<MigrateHandlerFn<Self, Self::CustomMigrateMsg, Self::Error>> {
122        let Some(handler) = self.maybe_migrate_handler() else {
123            return Err(AbstractSdkError::MissingHandler {
124                endpoint: "migrate".to_string(),
125            });
126        };
127        Ok(handler)
128    }
129
130    /// Get a sudo handler if it exists.
131    fn maybe_sudo_handler(&self) -> Option<SudoHandlerFn<Self, Self::SudoMsg, Self::Error>> {
132        let contract = self.contract();
133        contract.sudo_handler
134    }
135    /// Get a sudo handler or return an error.
136    fn sudo_handler(&self) -> AbstractSdkResult<SudoHandlerFn<Self, Self::SudoMsg, Self::Error>> {
137        let Some(handler) = self.maybe_sudo_handler() else {
138            return Err(AbstractSdkError::MissingHandler {
139                endpoint: "sudo".to_string(),
140            });
141        };
142        Ok(handler)
143    }
144
145    /// Get an ibc callback handler if it exists.
146    fn maybe_ibc_callback_handler(&self) -> Option<IbcCallbackHandlerFn<Self, Self::Error>> {
147        let contract = self.contract();
148        contract.ibc_callback_handler
149    }
150    /// Get an IBC module call handler if it exists.
151    fn maybe_module_ibc_handler(&self) -> Option<ModuleIbcHandlerFn<Self, Self::Error>> {
152        let contract = self.contract();
153        contract.module_ibc_handler
154    }
155    /// Get a reply handler if it exists.
156    fn maybe_reply_handler(&self, id: u64) -> Option<ReplyHandlerFn<Self, Self::Error>> {
157        let contract = self.contract();
158        for reply_handlers in contract.reply_handlers {
159            for handler in reply_handlers {
160                if handler.0 == id {
161                    return Some(handler.1);
162                }
163            }
164        }
165        None
166    }
167    /// Get a reply handler or return an error.
168    fn reply_handler(&self, id: u64) -> AbstractSdkResult<ReplyHandlerFn<Self, Self::Error>> {
169        let Some(handler) = self.maybe_reply_handler(id) else {
170            return Err(AbstractSdkError::MissingHandler {
171                endpoint: format! {"reply with id {id}"},
172            });
173        };
174        Ok(handler)
175    }
176}