komple_framework_attribute_permission/
contract.rs1#[cfg(not(feature = "library"))]
2use cosmwasm_std::entry_point;
3use cosmwasm_std::{
4 from_binary, to_binary, Addr, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdResult,
5};
6use cw2::set_contract_version;
7use komple_framework_metadata_module::helper::KompleMetadataModule;
8use komple_framework_types::modules::permission::AttributeConditions;
9use komple_framework_types::modules::Modules;
10use komple_framework_types::shared::query::ResponseWrapper;
11use komple_framework_types::shared::{RegisterMsg, PARENT_ADDR_NAMESPACE};
12use komple_framework_utils::response::EventHelper;
13use komple_framework_utils::response::ResponseHelper;
14use komple_framework_utils::storage::StorageHelper;
15
16use crate::error::ContractError;
17use crate::msg::{AttributeMsg, AttributeTypes, ExecuteMsg, QueryMsg};
18use crate::state::{Config, CONFIG, PERMISSION_MODULE_ADDR};
19
20const CONTRACT_NAME: &str = "crates.io:komple-framework-attribute-permission";
22const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
23
24#[cfg_attr(not(feature = "library"), entry_point)]
25pub fn instantiate(
26 deps: DepsMut,
27 _env: Env,
28 info: MessageInfo,
29 msg: RegisterMsg,
30) -> Result<Response, ContractError> {
31 set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
32
33 let admin = deps.api.addr_validate(&msg.admin)?;
34 let config = Config {
35 admin: admin.clone(),
36 };
37 CONFIG.save(deps.storage, &config)?;
38
39 PERMISSION_MODULE_ADDR.save(deps.storage, &info.sender)?;
40
41 Ok(
42 ResponseHelper::new_permission("attribute", "instantiate").add_event(
43 EventHelper::new("attribute_permission_instantiate")
44 .add_attribute("admin", admin)
45 .add_attribute("permission_module_addr", info.sender)
46 .get(),
47 ),
48 )
49}
50
51#[cfg_attr(not(feature = "library"), entry_point)]
52pub fn execute(
53 deps: DepsMut,
54 env: Env,
55 info: MessageInfo,
56 msg: ExecuteMsg,
57) -> Result<Response, ContractError> {
58 match msg {
59 ExecuteMsg::Check { data } => execute_check(deps, env, info, data),
60 }
61}
62
63pub fn execute_check(
64 deps: DepsMut,
65 _env: Env,
66 _info: MessageInfo,
67 data: Binary,
68) -> Result<Response, ContractError> {
69 let permission_addr = PERMISSION_MODULE_ADDR.load(deps.storage)?;
70 let hub_addr = StorageHelper::query_storage::<Addr>(
71 &deps.querier,
72 &permission_addr,
73 PARENT_ADDR_NAMESPACE,
74 )?;
75 let mint_module_addr = StorageHelper::query_module_address(
76 &deps.querier,
77 &hub_addr.unwrap(),
78 Modules::Mint.to_string(),
79 )?;
80
81 let msgs: Vec<AttributeMsg> = from_binary(&data)?;
82
83 for msg in msgs {
85 let collection_addr = StorageHelper::query_collection_address(
87 &deps.querier,
88 &mint_module_addr,
89 &msg.collection_id,
90 )?;
91
92 let sub_modules = StorageHelper::query_token_sub_modules(&deps.querier, &collection_addr)?;
94 if sub_modules.metadata.is_none() {
95 return Err(ContractError::MetadataNotFound {});
96 };
97
98 let response = KompleMetadataModule(sub_modules.metadata.unwrap())
100 .query_metadata(&deps.querier, msg.token_id)?;
101 let attributes = response.metadata.attributes;
102
103 let attribute = attributes
105 .into_iter()
106 .find(|attr| attr.trait_type == msg.trait_type);
107
108 if msg.condition != AttributeConditions::Absent && attribute.is_none() {
110 return Err(ContractError::AttributeNotFound {});
111 }
112 if msg.condition == AttributeConditions::GreaterThan
115 || msg.condition == AttributeConditions::GreaterThanOrEqual
116 || msg.condition == AttributeConditions::LessThan
117 || msg.condition == AttributeConditions::LessThanOrEqual
118 {
119 if get_value_type(&msg.value) != AttributeTypes::Integer
121 && get_value_type(&attribute.as_ref().unwrap().value) != AttributeTypes::Integer
122 {
123 return Err(ContractError::AttributeTypeMismatch {});
124 }
125 }
126 match msg.condition {
128 AttributeConditions::Absent => {
129 if attribute.is_some() {
130 return Err(ContractError::AttributeFound {});
131 }
132 }
133 AttributeConditions::Equal => {
134 if attribute.unwrap().value != msg.value {
135 return Err(ContractError::AttributeNotEqual {});
136 }
137 }
138 AttributeConditions::NotEqual => {
139 if attribute.unwrap().value == msg.value {
140 return Err(ContractError::AttributeEqual {});
141 }
142 }
143 AttributeConditions::GreaterThan => {
144 let attribute_value = attribute.as_ref().unwrap().value.parse::<u32>()?;
145 let msg_value = msg.value.parse::<u32>().unwrap();
146 if attribute_value <= msg_value {
147 return Err(ContractError::AttributeLessThanOrEqual {});
148 }
149 }
150 AttributeConditions::GreaterThanOrEqual => {
151 let attribute_value = attribute.as_ref().unwrap().value.parse::<u32>()?;
152 let msg_value = msg.value.parse::<u32>().unwrap();
153 if attribute_value < msg_value {
154 return Err(ContractError::AttributeLessThan {});
155 }
156 }
157 AttributeConditions::LessThan => {
158 let attribute_value = attribute.as_ref().unwrap().value.parse::<u32>()?;
159 let msg_value = msg.value.parse::<u32>().unwrap();
160 if attribute_value >= msg_value {
161 return Err(ContractError::AttributeGreaterThanOrEqual {});
162 }
163 }
164 AttributeConditions::LessThanOrEqual => {
165 let attribute_value = attribute.as_ref().unwrap().value.parse::<u32>()?;
166 let msg_value = msg.value.parse::<u32>().unwrap();
167 if attribute_value > msg_value {
168 return Err(ContractError::AttributeGreaterThan {});
169 }
170 }
171 _ => {}
172 };
173 }
174
175 Ok(
176 ResponseHelper::new_permission("attribute", "check").add_event(
177 EventHelper::new("attribute_permission_check")
178 .get(),
180 ),
181 )
182}
183
184fn get_value_type(value: &str) -> AttributeTypes {
187 if value.parse::<u32>().is_ok() {
188 return AttributeTypes::Integer;
189 }
190 if value.parse::<bool>().is_ok() {
191 return AttributeTypes::Boolean;
192 }
193 AttributeTypes::String
194}
195
196#[cfg_attr(not(feature = "library"), entry_point)]
197pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
198 match msg {
199 QueryMsg::Config {} => to_binary(&query_config(deps)?),
200 }
201}
202
203fn query_config(deps: Deps) -> StdResult<ResponseWrapper<Config>> {
204 let config = CONFIG.load(deps.storage)?;
205 Ok(ResponseWrapper {
206 query: "config".to_string(),
207 data: config,
208 })
209}