abstract_core/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    /// Core Abstract Contracts
9    AccountBase(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}
19
20impl ModuleReference {
21    /// Validates that addresses are valid
22    pub fn validate(&self, deps: Deps) -> AbstractResult<()> {
23        match self {
24            ModuleReference::Native(addr) => {
25                deps.api.addr_validate(addr.as_str())?;
26            }
27            ModuleReference::Adapter(addr) => {
28                deps.api.addr_validate(addr.as_str())?;
29            }
30            _ => (),
31        };
32        Ok(())
33    }
34
35    pub fn unwrap_account(&self) -> AbstractResult<u64> {
36        match self {
37            ModuleReference::AccountBase(v) => Ok(*v),
38            _ => Err(AbstractError::Assert(
39                "module reference not an account module.".to_string(),
40            )),
41        }
42    }
43
44    pub fn unwrap_native(&self) -> AbstractResult<Addr> {
45        match self {
46            ModuleReference::Native(addr) => Ok(addr.clone()),
47            _ => Err(AbstractError::Assert(
48                "module reference not a native module.".to_string(),
49            )),
50        }
51    }
52
53    pub fn unwrap_adapter(&self) -> AbstractResult<Addr> {
54        match self {
55            ModuleReference::Adapter(addr) => Ok(addr.clone()),
56            _ => Err(AbstractError::Assert(
57                "module reference not an api module.".to_string(),
58            )),
59        }
60    }
61
62    pub fn unwrap_app(&self) -> AbstractResult<u64> {
63        match self {
64            ModuleReference::App(v) => Ok(*v),
65            _ => Err(AbstractError::Assert(
66                "module reference not an app module.".to_string(),
67            )),
68        }
69    }
70
71    pub fn unwrap_standalone(&self) -> AbstractResult<u64> {
72        match self {
73            ModuleReference::Standalone(v) => Ok(*v),
74            _ => Err(AbstractError::Assert(
75                "module reference not a standalone module.".to_string(),
76            )),
77        }
78    }
79
80    /// Unwraps the module reference and returns the address of the module.
81    /// Throws an error if the module reference is not an address.
82    pub fn unwrap_addr(&self) -> AbstractResult<Addr> {
83        match self {
84            ModuleReference::Native(addr) => Ok(addr.clone()),
85            ModuleReference::Adapter(addr) => Ok(addr.clone()),
86            _ => Err(AbstractError::Assert(
87                "module reference not a native or api module.".to_string(),
88            )),
89        }
90    }
91
92    // Unwraps the module reference and returns code id of the module
93    // Throws an error if the module reference is not an code id
94    pub fn unwrap_code_id(&self) -> AbstractResult<u64> {
95        match self {
96            ModuleReference::AccountBase(code_id)
97            | ModuleReference::App(code_id)
98            | ModuleReference::Standalone(code_id) => Ok(*code_id),
99            _ => Err(AbstractError::Assert(
100                "module reference not account base, app or standalone".to_owned(),
101            )),
102        }
103    }
104}
105
106#[cfg(test)]
107mod test {
108    use cosmwasm_std::testing::mock_dependencies;
109    use speculoos::prelude::*;
110
111    use super::*;
112
113    #[test]
114    fn core() {
115        let account_base = ModuleReference::AccountBase(1);
116        assert_eq!(account_base.unwrap_account().unwrap(), 1);
117        assert!(account_base.unwrap_native().is_err());
118        assert!(account_base.unwrap_adapter().is_err());
119        assert!(account_base.unwrap_app().is_err());
120        assert!(account_base.unwrap_standalone().is_err());
121    }
122    #[test]
123    fn native() {
124        let native = ModuleReference::Native(Addr::unchecked("addr"));
125        assert!(native.unwrap_account().is_err());
126        assert_eq!(native.unwrap_native().unwrap(), Addr::unchecked("addr"));
127        assert!(native.unwrap_adapter().is_err());
128        assert!(native.unwrap_app().is_err());
129        assert!(native.unwrap_standalone().is_err());
130    }
131
132    #[test]
133    fn adapter() {
134        let adapter = ModuleReference::Adapter(Addr::unchecked("addr"));
135        assert!(adapter.unwrap_account().is_err());
136        assert!(adapter.unwrap_native().is_err());
137        assert_eq!(adapter.unwrap_adapter().unwrap(), Addr::unchecked("addr"));
138        assert!(adapter.unwrap_app().is_err());
139        assert!(adapter.unwrap_standalone().is_err());
140    }
141
142    #[test]
143    fn app() {
144        let app = ModuleReference::App(1);
145        assert!(app.unwrap_account().is_err());
146        assert!(app.unwrap_native().is_err());
147        assert!(app.unwrap_adapter().is_err());
148        assert_eq!(app.unwrap_app().unwrap(), 1);
149        assert!(app.unwrap_standalone().is_err());
150    }
151
152    #[test]
153    fn standalone() {
154        let standalone = ModuleReference::Standalone(1);
155        assert!(standalone.unwrap_account().is_err());
156        assert!(standalone.unwrap_native().is_err());
157        assert!(standalone.unwrap_adapter().is_err());
158        assert!(standalone.unwrap_app().is_err());
159        assert_eq!(standalone.unwrap_standalone().unwrap(), 1);
160    }
161
162    #[test]
163    fn unwrap_addr() {
164        let native = ModuleReference::Native(Addr::unchecked("addr"));
165        assert_eq!(native.unwrap_addr().unwrap(), Addr::unchecked("addr"));
166        let api = ModuleReference::Adapter(Addr::unchecked("addr"));
167        assert_eq!(api.unwrap_addr().unwrap(), Addr::unchecked("addr"));
168
169        let account_base = ModuleReference::AccountBase(1);
170        assert!(account_base.unwrap_addr().is_err());
171    }
172
173    #[test]
174    fn test_validate_happy_path() {
175        let deps = mock_dependencies();
176
177        let native = ModuleReference::Native(Addr::unchecked("addr"));
178        assert_that!(native.validate(deps.as_ref())).is_ok();
179
180        let api = ModuleReference::Adapter(Addr::unchecked("addr"));
181        assert_that!(api.validate(deps.as_ref())).is_ok();
182
183        let account_base = ModuleReference::AccountBase(1);
184        assert_that!(account_base.validate(deps.as_ref())).is_ok();
185
186        let app = ModuleReference::App(1);
187        assert_that!(app.validate(deps.as_ref())).is_ok();
188
189        let standalone = ModuleReference::Standalone(1);
190        assert_that!(standalone.validate(deps.as_ref())).is_ok();
191    }
192
193    #[test]
194    fn test_validate_bad_address() {
195        let deps = mock_dependencies();
196
197        let native = ModuleReference::Native(Addr::unchecked(""));
198        assert_that!(native.validate(deps.as_ref())).is_err();
199
200        let api = ModuleReference::Adapter(Addr::unchecked(""));
201        assert_that!(api.validate(deps.as_ref())).is_err();
202    }
203}