polytone_proxy/
contract.rs

1#[cfg(not(feature = "library"))]
2use cosmwasm_std::entry_point;
3use cosmwasm_std::{
4    to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg,
5    SubMsgResponse, SubMsgResult,
6};
7use cw2::set_contract_version;
8use polytone::ack::ack_execute_success;
9
10use crate::error::ContractError;
11use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
12use crate::state::{COLLECTOR, INSTANTIATOR};
13
14const CONTRACT_NAME: &str = "crates.io:polytone-proxy";
15const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
16
17#[cfg_attr(not(feature = "library"), entry_point)]
18pub fn instantiate(
19    deps: DepsMut,
20    _env: Env,
21    info: MessageInfo,
22    _msg: InstantiateMsg,
23) -> Result<Response, ContractError> {
24    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
25    INSTANTIATOR.save(deps.storage, &info.sender)?;
26
27    Ok(Response::default()
28        .add_attribute("method", "instantiate")
29        .add_attribute("owner", info.sender))
30}
31
32#[cfg_attr(not(feature = "library"), entry_point)]
33pub fn execute(
34    deps: DepsMut,
35    env: Env,
36    info: MessageInfo,
37    msg: ExecuteMsg,
38) -> Result<Response, ContractError> {
39    match msg {
40        ExecuteMsg::Proxy { msgs } => {
41            if info.sender == INSTANTIATOR.load(deps.storage)? {
42                let response = Response::default()
43                    .add_attribute("method", "execute_proxy")
44                    .add_attribute("sender", info.sender);
45                if msgs.is_empty() {
46                    Ok(response.set_data(ack_execute_success(
47                        vec![],
48                        env.contract.address.into_string(),
49                    )))
50                } else {
51                    COLLECTOR.save(deps.storage, &vec![None; msgs.len()])?;
52                    Ok(response.add_submessages(
53                        msgs.into_iter()
54                            .enumerate()
55                            .map(|(id, msg)| SubMsg::reply_always(msg, id as u64)),
56                    ))
57                }
58            } else {
59                Err(ContractError::NotInstantiator)
60            }
61        }
62    }
63}
64
65#[cfg_attr(not(feature = "library"), entry_point)]
66pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
67    match msg {
68        QueryMsg::Instantiator {} => to_binary(&INSTANTIATOR.load(deps.storage)?),
69    }
70}
71
72#[cfg_attr(not(feature = "library"), entry_point)]
73pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result<Response, ContractError> {
74    let mut collector = COLLECTOR.load(deps.storage)?;
75
76    match msg.result {
77        SubMsgResult::Err(error) => Err(ContractError::MsgError {
78            index: msg.id,
79            error,
80        }),
81        SubMsgResult::Ok(res) => {
82            collector[msg.id as usize] = Some(res);
83
84            if msg.id + 1 == collector.len() as u64 {
85                COLLECTOR.remove(deps.storage);
86                let collector = collector
87                    .into_iter()
88                    .map(|res| res.unwrap())
89                    .collect::<Vec<SubMsgResponse>>();
90                Ok(Response::default()
91                    .add_attribute("callbacks_processed", (msg.id + 1).to_string())
92                    .set_data(ack_execute_success(
93                        collector,
94                        env.contract.address.into_string(),
95                    )))
96            } else {
97                COLLECTOR.save(deps.storage, &collector)?;
98                Ok(Response::default())
99            }
100        }
101    }
102}