1#[cfg(not(feature = "library"))]
2use cosmwasm_std::entry_point;
3use cosmwasm_std::{to_json_binary, Addr, Binary, Deps, Env, Order, StdError, StdResult, Uint128};
4use cw_storage_plus::Bound;
5
6use astroport_governance::builder_unlock::{
7 AllocationParams, AllocationResponse, QueryMsg, SimulateWithdrawResponse, State,
8};
9use astroport_governance::{DEFAULT_LIMIT, MAX_LIMIT};
10
11use crate::error::ContractError;
12use crate::state::{Allocation, CONFIG, PARAMS, STATE, STATUS};
13
14#[cfg_attr(not(feature = "library"), entry_point)]
27pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
28 match msg {
29 QueryMsg::Config {} => to_json_binary(&CONFIG.load(deps.storage)?),
30 QueryMsg::State { timestamp } => to_json_binary(&query_state(deps, timestamp)?),
31 QueryMsg::Allocation { account, timestamp } => {
32 to_json_binary(&query_allocation(deps, account, timestamp)?)
33 }
34 QueryMsg::UnlockedTokens { account } => to_json_binary(
35 &query_tokens_unlocked(deps, env, account)
36 .map_err(|err| StdError::generic_err(err.to_string()))?,
37 ),
38 QueryMsg::SimulateWithdraw { account, timestamp } => to_json_binary(
39 &query_simulate_withdraw(deps, env, account, timestamp)
40 .map_err(|err| StdError::generic_err(err.to_string()))?,
41 ),
42 QueryMsg::Allocations { start_after, limit } => {
43 to_json_binary(&query_allocations(deps, start_after, limit)?)
44 }
45 }
46}
47
48pub fn query_state(deps: Deps, timestamp: Option<u64>) -> StdResult<State> {
50 if let Some(timestamp) = timestamp {
51 STATE.may_load_at_height(deps.storage, timestamp)
53 } else {
54 STATE.may_load(deps.storage)
56 }
57 .map(|state| state.unwrap_or_default())
58}
59
60pub fn query_allocation(
66 deps: Deps,
67 account: String,
68 timestamp: Option<u64>,
69) -> StdResult<AllocationResponse> {
70 let receiver = deps.api.addr_validate(&account)?;
71 let params = PARAMS
72 .may_load(deps.storage, &receiver)?
73 .unwrap_or_default();
74
75 let status = if let Some(timestamp) = timestamp {
76 STATUS
78 .may_load_at_height(deps.storage, &receiver, timestamp)?
79 .unwrap_or_default()
80 } else {
81 STATUS
83 .may_load(deps.storage, &receiver)?
84 .unwrap_or_default()
85 };
86
87 Ok(AllocationResponse { params, status })
88}
89
90pub fn query_allocations(
96 deps: Deps,
97 start_after: Option<String>,
98 limit: Option<u32>,
99) -> StdResult<Vec<(Addr, AllocationParams)>> {
100 let limit = limit.unwrap_or(DEFAULT_LIMIT).min(MAX_LIMIT) as usize;
101 let default_start;
102
103 let start = if let Some(start_after) = start_after {
104 default_start = deps.api.addr_validate(&start_after)?;
105 Some(Bound::exclusive(&default_start))
106 } else {
107 None
108 };
109
110 PARAMS
111 .range(deps.storage, start, None, Order::Ascending)
112 .take(limit)
113 .collect()
114}
115
116pub fn query_tokens_unlocked(
120 deps: Deps,
121 env: Env,
122 account: String,
123) -> Result<Uint128, ContractError> {
124 let receiver = deps.api.addr_validate(&account)?;
125 let block_ts = env.block.time.seconds();
126 let allocation = Allocation::must_load(deps.storage, block_ts, &receiver)?;
127
128 Ok(allocation.compute_unlocked_amount(block_ts))
129}
130
131pub fn query_simulate_withdraw(
137 deps: Deps,
138 env: Env,
139 account: String,
140 timestamp: Option<u64>,
141) -> Result<SimulateWithdrawResponse, ContractError> {
142 let receiver = deps.api.addr_validate(&account)?;
143 let allocation = Allocation::must_load(deps.storage, env.block.time.seconds(), &receiver)?;
144 let timestamp = timestamp.unwrap_or_else(|| env.block.time.seconds());
145
146 Ok(allocation.compute_withdraw_amount(timestamp))
147}