use cosmwasm_std::{
entry_point, to_binary, Binary, Deps, DepsMut, Env, MessageInfo,
Response, StdResult, Uint128, Decimal, StdError,
};
use neutron_sdk::bindings::msg::NeutronMsg;
use neutron_sdk::bindings::query::NeutronQuery;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg, CountResponse, ConfigResponse, PriceResponse};
use crate::state::{COUNTER, PRICE_THRESHOLD, LAST_PRICE, Config};
#[entry_point]
pub fn instantiate(
deps: DepsMut,
_env: Env,
_info: MessageInfo,
msg: InstantiateMsg,
) -> StdResult<Response> {
// Save initial state
COUNTER.save(deps.storage, &msg.initial_count)?;
PRICE_THRESHOLD.save(deps.storage, &msg.price_threshold)?;
// Save oracle configuration
let config = Config {
price_threshold: msg.price_threshold,
oracle_base: msg.oracle_base,
oracle_quote: msg.oracle_quote,
};
Ok(Response::new()
.add_attribute("action", "instantiate")
.add_attribute("threshold", msg.price_threshold.to_string()))
}
#[entry_point]
pub fn execute(
deps: DepsMut,
env: Env,
info: MessageInfo,
msg: ExecuteMsg,
) -> StdResult<Response> {
match msg {
ExecuteMsg::Increment { amount } => increment(deps, amount),
ExecuteMsg::UpdateThreshold { new_threshold } => {
update_threshold(deps, info, new_threshold)
}
ExecuteMsg::CheckPriceAndIncrement { amount } => {
check_price_and_increment(deps, env, amount)
}
}
}
fn increment(deps: DepsMut, amount: Uint128) -> StdResult<Response> {
if amount > Uint128::from(100u128) {
return Err(StdError::generic_err("Cannot increment by more than 100"));
}
let current = COUNTER.load(deps.storage)?;
let new_count = current + amount;
COUNTER.save(deps.storage, &new_count)?;
Ok(Response::new()
.add_attribute("action", "increment")
.add_attribute("amount", amount.to_string())
.add_attribute("new_count", new_count.to_string()))
}
fn check_price_and_increment(
deps: DepsMut,
env: Env,
amount: Uint128
) -> StdResult<Response> {
// Query current price from Oracle module
let price_query = NeutronQuery::Oracle {
base: "ATOM".to_string(),
quote: "USD".to_string(),
};
let price_response: PriceResponse = deps.querier.query(&price_query.into())?;
let current_price = price_response.price;
// Save the price for future reference
LAST_PRICE.save(deps.storage, ¤t_price)?;
// Check if price meets threshold
let threshold = PRICE_THRESHOLD.load(deps.storage)?;
if current_price < threshold {
return Err(StdError::generic_err(
format!("Price {} is below threshold {}", current_price, threshold)
));
}
// Price is good, increment the counter
increment(deps, amount)
}
#[entry_point]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
match msg {
QueryMsg::GetCount {} => {
let count = COUNTER.load(deps.storage)?;
let response = CountResponse { count };
to_binary(&response)
}
QueryMsg::GetLastPrice {} => {
let price = LAST_PRICE.may_load(deps.storage)?.unwrap_or_default();
let response = PriceResponse { price };
to_binary(&response)
}
QueryMsg::GetConfig {} => {
let threshold = PRICE_THRESHOLD.load(deps.storage)?;
let response = ConfigResponse {
price_threshold: threshold,
oracle_base: "ATOM".to_string(),
oracle_quote: "USD".to_string(),
};
to_binary(&response)
}
}
}