1use cosmwasm_std::entry_point;
2use cosmwasm_std::{
3 coin, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, StdError, StdResult,
4};
5#[cfg(not(feature = "library"))]
6use cw2::set_contract_version;
7use cw20::{Balance, BalanceResponse};
8use mod_sdk::types::QueryResponse;
9
10use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
11use crate::types::{BalanceComparator, HasBalanceComparator};
12use crate::ContractError;
13
14const CONTRACT_NAME: &str = "crate:croncat-mod-balances";
16const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
17
18#[cfg_attr(not(feature = "library"), entry_point)]
19pub fn instantiate(
20 deps: DepsMut,
21 _env: Env,
22 _info: MessageInfo,
23 msg: InstantiateMsg,
24) -> Result<Response, StdError> {
25 let contract_version = msg.version.unwrap_or_else(|| CONTRACT_VERSION.to_string());
26 set_contract_version(deps.storage, CONTRACT_NAME, &contract_version)?;
27
28 Ok(Response::new().add_attribute("action", "instantiate"))
29}
30
31#[cfg_attr(not(feature = "library"), entry_point)]
32pub fn execute(
33 _deps: DepsMut,
34 _env: Env,
35 _info: MessageInfo,
36 _msg: ExecuteMsg,
37) -> Result<Response, ContractError> {
38 Err(ContractError::Noop)
39}
40
41#[cfg_attr(not(feature = "library"), entry_point)]
42pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
43 match msg {
44 QueryMsg::GetBalance { address, denom } => {
45 to_binary(&query_get_balance(deps, address, denom)?)
46 }
47 QueryMsg::GetCw20Balance {
48 cw20_contract,
49 address,
50 } => to_binary(&query_get_cw20_balance(deps, cw20_contract, address)?),
51 QueryMsg::HasBalanceComparator(HasBalanceComparator {
52 address,
53 required_balance,
54 comparator,
55 }) => to_binary(&query_has_balance_comparator(
56 deps,
57 address,
58 required_balance,
59 comparator,
60 )?),
61 }
62}
63
64fn query_get_balance(deps: Deps, address: String, denom: String) -> StdResult<QueryResponse> {
71 let valid_addr = deps.api.addr_validate(&address)?;
72 let coin = deps.querier.query_balance(valid_addr, denom)?;
73 Ok(QueryResponse {
74 result: true,
75 data: to_binary(&coin)?,
76 })
77}
78
79fn query_get_cw20_balance(
86 deps: Deps,
87 cw20_contract: String,
88 address: String,
89) -> StdResult<QueryResponse> {
90 let valid_cw20 = deps.api.addr_validate(&cw20_contract)?;
91 let valid_address = deps.api.addr_validate(&address)?;
92 let balance_response: BalanceResponse = deps.querier.query_wasm_smart(
93 valid_cw20,
94 &cw20::Cw20QueryMsg::Balance {
95 address: valid_address.to_string(),
96 },
97 )?;
98 let coin = coin(balance_response.balance.into(), cw20_contract);
99 Ok(QueryResponse {
100 result: true,
101 data: to_binary(&coin)?,
102 })
103}
104
105fn query_has_balance_comparator(
115 deps: Deps,
116 address: String,
117 required_balance: Balance,
118 comparator: BalanceComparator,
119) -> StdResult<QueryResponse> {
120 let valid_address = deps.api.addr_validate(&address)?;
121
122 let (balance_amount, denom, required_amount) = match required_balance {
124 Balance::Native(required_native) => {
125 let native_vec = required_native.into_vec();
128 let native = native_vec.first().cloned();
129 if let Some(native) = native {
130 let balance = deps.querier.query_balance(valid_address, native.denom)?;
131 (balance.amount, balance.denom, native.amount)
132 } else {
133 return Ok(QueryResponse {
134 result: false,
135 data: Default::default(),
136 });
137 }
138 }
139 Balance::Cw20(required_cw20) => {
140 let balance_response: BalanceResponse = deps.querier.query_wasm_smart(
141 required_cw20.address.clone(),
142 &cw20::Cw20QueryMsg::Balance { address },
143 )?;
144 (
145 balance_response.balance,
146 required_cw20.address.to_string(),
147 required_cw20.amount,
148 )
149 }
150 };
151
152 let result = match comparator {
153 BalanceComparator::Eq => required_amount == balance_amount,
154 BalanceComparator::Ne => required_amount != balance_amount,
155 BalanceComparator::Gt => required_amount < balance_amount,
156 BalanceComparator::Gte => required_amount <= balance_amount,
157 BalanceComparator::Lt => required_amount > balance_amount,
158 BalanceComparator::Lte => required_amount >= balance_amount,
159 };
160
161 let coin = coin(balance_amount.into(), denom);
162 Ok(QueryResponse {
163 result,
164 data: to_binary(&coin)?,
165 })
166}