1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use abstract_os::{
api::{BaseExecuteMsg, ExecuteMsg},
manager::state::{ModuleId, OS_MODULES},
};
use cosmwasm_std::{
wasm_execute, Addr, CosmosMsg, Deps, Empty, QueryRequest, StdError, StdResult, WasmQuery,
};
use cw2::{ContractVersion, CONTRACT};
use serde::Serialize;
use super::{Dependencies, Identification};
pub trait ApplicationInterface: Identification + Dependencies {
fn applications<'a>(&'a self, deps: Deps<'a>) -> Applications<Self> {
Applications { base: self, deps }
}
}
impl<T> ApplicationInterface for T where T: Identification + Dependencies {}
#[derive(Clone)]
pub struct Applications<'a, T: ApplicationInterface> {
base: &'a T,
deps: Deps<'a>,
}
impl<'a, T: ApplicationInterface> Applications<'a, T> {
pub fn app_address(&self, module_id: ModuleId) -> StdResult<Addr> {
let manager_addr = self.base.manager_address(self.deps)?;
let maybe_module_addr = OS_MODULES.query(&self.deps.querier, manager_addr, module_id)?;
let Some(module_addr) = maybe_module_addr else {
return Err(StdError::generic_err(format!("Module {} not enabled on OS.",module_id)));
};
Ok(module_addr)
}
pub fn app_version(&self, app_id: ModuleId) -> StdResult<ContractVersion> {
let app_address = self.app_address(app_id)?;
let req = QueryRequest::Wasm(WasmQuery::Raw {
contract_addr: app_address.into(),
key: CONTRACT.as_slice().into(),
});
self.deps.querier.query::<ContractVersion>(&req)
}
pub fn api_request<M: Serialize>(
&self,
api_id: ModuleId,
message: impl Into<ExecuteMsg<M, Empty>>,
) -> StdResult<CosmosMsg> {
self.assert_app_is_dependency(api_id)?;
let api_msg: ExecuteMsg<M, Empty> = message.into();
let api_address = self.app_address(api_id)?;
Ok(wasm_execute(api_address, &api_msg, vec![])?.into())
}
pub fn configure_api(&self, api_id: ModuleId, message: BaseExecuteMsg) -> StdResult<CosmosMsg> {
let api_msg: ExecuteMsg<Empty, Empty> = message.into();
let api_address = self.app_address(api_id)?;
Ok(wasm_execute(api_address, &api_msg, vec![])?.into())
}
fn assert_app_is_dependency(&self, app: ModuleId) -> StdResult<()> {
let is_app_dependencies = Dependencies::dependencies(self.base)
.iter()
.map(|d| d.id)
.any(|x| x == app);
if !is_app_dependencies {
return Err(StdError::generic_err(format!(
"Module {} not defined as dependency on this module.",
app
)));
}
Ok(())
}
}