abstract_std/objects/
module_reference.rs

1use cosmwasm_std::{Addr, Deps};
2
3use crate::{error::AbstractError, AbstractResult};
4
5#[cosmwasm_schema::cw_serde]
6#[non_exhaustive]
7pub enum ModuleReference {
8    /// Account Contract
9    Account(u64),
10    /// Native Abstract Contracts
11    Native(Addr),
12    /// Installable adapters
13    Adapter(Addr),
14    /// Installable apps
15    App(u64),
16    /// A stand-alone contract
17    Standalone(u64),
18    /// A contract that exposes some service to others.
19    Service(Addr),
20}
21
22impl ModuleReference {
23    /// Validates that addresses are valid
24    pub fn validate(&self, deps: Deps) -> AbstractResult<()> {
25        match self {
26            ModuleReference::Native(addr)
27            | ModuleReference::Adapter(addr)
28            | ModuleReference::Service(addr) => {
29                deps.api.addr_validate(addr.as_str())?;
30            }
31            _ => (),
32        };
33        Ok(())
34    }
35
36    pub fn unwrap_account(&self) -> AbstractResult<u64> {
37        match self {
38            ModuleReference::Account(v) => Ok(*v),
39            _ => Err(AbstractError::Assert(
40                "module reference not an account module.".to_string(),
41            )),
42        }
43    }
44
45    pub fn unwrap_native(&self) -> AbstractResult<Addr> {
46        match self {
47            ModuleReference::Native(addr) => Ok(addr.clone()),
48            _ => Err(AbstractError::Assert(
49                "module reference not a native module.".to_string(),
50            )),
51        }
52    }
53
54    pub fn unwrap_adapter(&self) -> AbstractResult<Addr> {
55        match self {
56            ModuleReference::Adapter(addr) => Ok(addr.clone()),
57            _ => Err(AbstractError::Assert(
58                "module reference not an api module.".to_string(),
59            )),
60        }
61    }
62
63    pub fn unwrap_app(&self) -> AbstractResult<u64> {
64        match self {
65            ModuleReference::App(v) => Ok(*v),
66            _ => Err(AbstractError::Assert(
67                "module reference not an app module.".to_string(),
68            )),
69        }
70    }
71
72    pub fn unwrap_standalone(&self) -> AbstractResult<u64> {
73        match self {
74            ModuleReference::Standalone(v) => Ok(*v),
75            _ => Err(AbstractError::Assert(
76                "module reference not a standalone module.".to_string(),
77            )),
78        }
79    }
80
81    pub fn unwrap_service(&self) -> AbstractResult<Addr> {
82        match self {
83            ModuleReference::Service(addr) => Ok(addr.clone()),
84            _ => Err(AbstractError::Assert(
85                "module reference not a service module.".to_string(),
86            )),
87        }
88    }
89
90    /// Unwraps the module reference and returns the address of the module.
91    /// Throws an error if the module reference is not an address.
92    pub fn unwrap_addr(&self) -> AbstractResult<Addr> {
93        match self {
94            ModuleReference::Native(addr)
95            | ModuleReference::Adapter(addr)
96            | ModuleReference::Service(addr) => Ok(addr.clone()),
97            _ => Err(AbstractError::Assert(
98                "module reference not a native or api module.".to_string(),
99            )),
100        }
101    }
102
103    // Unwraps the module reference and returns code id of the module
104    // Throws an error if the module reference is not an code id
105    pub fn unwrap_code_id(&self) -> AbstractResult<u64> {
106        match self {
107            ModuleReference::Account(code_id)
108            | ModuleReference::App(code_id)
109            | ModuleReference::Standalone(code_id) => Ok(*code_id),
110            _ => Err(AbstractError::Assert(
111                "module reference not account, app or standalone".to_owned(),
112            )),
113        }
114    }
115}
116
117#[cfg(test)]
118mod test {
119    #![allow(clippy::needless_borrows_for_generic_args)]
120    use cosmwasm_std::testing::mock_dependencies;
121
122    use super::*;
123
124    #[coverage_helper::test]
125    fn core() {
126        let account = ModuleReference::Account(1);
127        assert_eq!(account.unwrap_account().unwrap(), 1);
128        assert!(account.unwrap_native().is_err());
129        assert!(account.unwrap_adapter().is_err());
130        assert!(account.unwrap_app().is_err());
131        assert!(account.unwrap_standalone().is_err());
132        assert!(account.unwrap_service().is_err());
133    }
134
135    #[coverage_helper::test]
136    fn native() {
137        let native = ModuleReference::Native(Addr::unchecked("addr"));
138        assert!(native.unwrap_account().is_err());
139        assert_eq!(native.unwrap_native().unwrap(), Addr::unchecked("addr"));
140        assert!(native.unwrap_adapter().is_err());
141        assert!(native.unwrap_app().is_err());
142        assert!(native.unwrap_standalone().is_err());
143        assert!(native.unwrap_service().is_err());
144    }
145
146    #[coverage_helper::test]
147    fn service() {
148        let service = ModuleReference::Service(Addr::unchecked("addr"));
149        assert!(service.unwrap_account().is_err());
150        assert!(service.unwrap_native().is_err());
151        assert!(service.unwrap_adapter().is_err());
152        assert!(service.unwrap_app().is_err());
153        assert!(service.unwrap_standalone().is_err());
154        assert_eq!(service.unwrap_service().unwrap(), Addr::unchecked("addr"));
155    }
156
157    #[coverage_helper::test]
158    fn adapter() {
159        let adapter = ModuleReference::Adapter(Addr::unchecked("addr"));
160        assert!(adapter.unwrap_account().is_err());
161        assert!(adapter.unwrap_native().is_err());
162        assert_eq!(adapter.unwrap_adapter().unwrap(), Addr::unchecked("addr"));
163        assert!(adapter.unwrap_app().is_err());
164        assert!(adapter.unwrap_standalone().is_err());
165        assert!(adapter.unwrap_service().is_err());
166    }
167
168    #[coverage_helper::test]
169    fn app() {
170        let app = ModuleReference::App(1);
171        assert!(app.unwrap_account().is_err());
172        assert!(app.unwrap_native().is_err());
173        assert!(app.unwrap_adapter().is_err());
174        assert_eq!(app.unwrap_app().unwrap(), 1);
175        assert!(app.unwrap_standalone().is_err());
176        assert!(app.unwrap_service().is_err());
177    }
178
179    #[coverage_helper::test]
180    fn standalone() {
181        let standalone = ModuleReference::Standalone(1);
182        assert!(standalone.unwrap_account().is_err());
183        assert!(standalone.unwrap_native().is_err());
184        assert!(standalone.unwrap_adapter().is_err());
185        assert!(standalone.unwrap_app().is_err());
186        assert_eq!(standalone.unwrap_standalone().unwrap(), 1);
187        assert!(standalone.unwrap_service().is_err());
188    }
189
190    #[coverage_helper::test]
191    fn unwrap_addr() {
192        let native = ModuleReference::Native(Addr::unchecked("addr"));
193        assert_eq!(native.unwrap_addr().unwrap(), Addr::unchecked("addr"));
194        let api = ModuleReference::Adapter(Addr::unchecked("addr"));
195        assert_eq!(api.unwrap_addr().unwrap(), Addr::unchecked("addr"));
196        let service = ModuleReference::Service(Addr::unchecked("addr"));
197        assert_eq!(service.unwrap_addr().unwrap(), Addr::unchecked("addr"));
198
199        let account = ModuleReference::Account(1);
200        assert!(account.unwrap_addr().is_err());
201    }
202
203    #[coverage_helper::test]
204    fn test_validate_happy_path() {
205        let deps = mock_dependencies();
206
207        let native = ModuleReference::Native(deps.api.addr_make("addr"));
208        assert!(native.validate(deps.as_ref()).is_ok());
209
210        let api = ModuleReference::Adapter(deps.api.addr_make("addr"));
211        assert!(api.validate(deps.as_ref()).is_ok());
212
213        let service = ModuleReference::Service(deps.api.addr_make("addr"));
214        assert!(service.validate(deps.as_ref()).is_ok());
215
216        let account = ModuleReference::Account(1);
217        assert!(account.validate(deps.as_ref()).is_ok());
218
219        let app = ModuleReference::App(1);
220        assert!(app.validate(deps.as_ref()).is_ok());
221
222        let standalone = ModuleReference::Standalone(1);
223        assert!(standalone.validate(deps.as_ref()).is_ok());
224    }
225
226    #[coverage_helper::test]
227    fn test_validate_bad_address() {
228        let deps = mock_dependencies();
229
230        let native = ModuleReference::Native(Addr::unchecked(""));
231        assert!(native.validate(deps.as_ref()).is_err());
232
233        let api = ModuleReference::Adapter(Addr::unchecked("abcde"));
234        assert!(api.validate(deps.as_ref()).is_err());
235
236        let service = ModuleReference::Service(Addr::unchecked("non_bech"));
237        assert!(service.validate(deps.as_ref()).is_err());
238    }
239}