Skip to main content

abstract_standalone/
state.rs

1use abstract_sdk::{
2    base::{ModuleId, ModuleMetadata, VersionString},
3    features::ModuleIdentification,
4    namespaces::{ADMIN_NAMESPACE, BASE_STATE},
5};
6use abstract_std::{
7    objects::{
8        dependency::StaticDependency, module::ModuleInfo, ownership::nested_admin::NestedAdmin,
9    },
10    standalone::StandaloneState,
11    AbstractResult,
12};
13use cosmwasm_std::{StdResult, Storage};
14use cw_storage_plus::Item;
15
16/// The state variables for our StandaloneContract.
17pub struct StandaloneContract {
18    pub admin: NestedAdmin,
19    pub(crate) base_state: Item<StandaloneState>,
20    /// Static info about the contract, used for migration
21    pub(crate) info: (ModuleId, VersionString, ModuleMetadata),
22    /// Modules that this contract depends on.
23    pub(crate) dependencies: &'static [StaticDependency],
24}
25
26impl ModuleIdentification for StandaloneContract {
27    fn module_id(&self) -> abstract_std::objects::module::ModuleId<'static> {
28        self.info.0
29    }
30}
31
32/// Constructor
33impl StandaloneContract {
34    pub const fn new(
35        name: &'static str,
36        version: &'static str,
37        metadata: Option<&'static str>,
38    ) -> Self {
39        Self {
40            admin: NestedAdmin::new(ADMIN_NAMESPACE),
41            base_state: Item::new(BASE_STATE),
42            info: (name, version, metadata),
43            dependencies: &[],
44        }
45    }
46
47    pub fn module_id(&self) -> &'static str {
48        self.info.0
49    }
50
51    pub fn version(&self) -> &'static str {
52        self.info.1
53    }
54
55    pub fn module_info(&self) -> AbstractResult<ModuleInfo> {
56        ModuleInfo::from_id(self.module_id(), self.version().into())
57    }
58
59    /// add dependencies to the contract
60    pub const fn with_dependencies(mut self, dependencies: &'static [StaticDependency]) -> Self {
61        self.dependencies = dependencies;
62        self
63    }
64
65    pub fn load_state(&self, store: &dyn Storage) -> StdResult<StandaloneState> {
66        self.base_state.load(store)
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use abstract_sdk::features::Dependencies;
73    use abstract_std::{
74        objects::{dependency::StaticDependency, module::ModuleInfo},
75        standalone::StandaloneState,
76        ACCOUNT,
77    };
78    use abstract_testing::prelude::*;
79
80    use crate::mock::{mock_init, MockStandaloneContract, BASIC_MOCK_STANDALONE};
81
82    #[coverage_helper::test]
83    fn builder() {
84        let standalone = MockStandaloneContract::new(TEST_MODULE_ID, TEST_VERSION, None)
85            .with_dependencies(&[StaticDependency {
86                id: ACCOUNT,
87                version_req: &[TEST_VERSION],
88            }]);
89        assert_eq!(standalone.module_id(), TEST_MODULE_ID);
90        assert_eq!(standalone.version(), TEST_VERSION);
91        assert_eq!(
92            standalone.module_info(),
93            Ok(ModuleInfo::from_id(TEST_MODULE_ID, TEST_VERSION.parse().unwrap()).unwrap())
94        );
95        assert_eq!(
96            standalone.dependencies(),
97            &[StaticDependency {
98                id: ACCOUNT,
99                version_req: &[TEST_VERSION],
100            }]
101        );
102    }
103
104    #[coverage_helper::test]
105    fn load_state() {
106        let deps = mock_init(true);
107        let account = test_account(deps.api);
108        let state = BASIC_MOCK_STANDALONE.load_state(&deps.storage).unwrap();
109
110        assert_eq!(
111            state,
112            StandaloneState {
113                account: account.clone(),
114                is_migratable: true
115            }
116        );
117
118        let deps = mock_init(false);
119        let state = BASIC_MOCK_STANDALONE.load_state(&deps.storage).unwrap();
120
121        assert_eq!(
122            state,
123            StandaloneState {
124                account: account.clone(),
125                is_migratable: false
126            }
127        );
128    }
129}