abstract-polytone-proxy 5.0.0

An Interchain Account contract.
Documentation
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
    to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdResult, SubMsg,
    SubMsgResponse, SubMsgResult,
};
use cw2::set_contract_version;
use polytone::ack::ack_execute_success;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, InstantiateMsg, QueryMsg};
use crate::state::{COLLECTOR, INSTANTIATOR};

const CONTRACT_NAME: &str = "crates.io:polytone-proxy";
const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn instantiate(
    deps: DepsMut,
    _env: Env,
    info: MessageInfo,
    _msg: InstantiateMsg,
) -> Result<Response, ContractError> {
    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
    INSTANTIATOR.save(deps.storage, &info.sender)?;

    Ok(Response::default()
        .add_attribute("method", "instantiate")
        .add_attribute("owner", info.sender))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    match msg {
        ExecuteMsg::Proxy { msgs } => {
            if info.sender == INSTANTIATOR.load(deps.storage)? {
                let response = Response::default()
                    .add_attribute("method", "execute_proxy")
                    .add_attribute("sender", info.sender);
                if msgs.is_empty() {
                    Ok(response.set_data(ack_execute_success(
                        vec![],
                        env.contract.address.into_string(),
                    )))
                } else {
                    COLLECTOR.save(deps.storage, &vec![None; msgs.len()])?;
                    Ok(response.add_submessages(
                        msgs.into_iter()
                            .enumerate()
                            .map(|(id, msg)| SubMsg::reply_always(msg, id as u64)),
                    ))
                }
            } else {
                Err(ContractError::NotInstantiator)
            }
        }
    }
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::Instantiator {} => to_json_binary(&INSTANTIATOR.load(deps.storage)?),
    }
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn reply(deps: DepsMut, env: Env, msg: Reply) -> Result<Response, ContractError> {
    let mut collector = COLLECTOR.load(deps.storage)?;

    match msg.result {
        SubMsgResult::Err(error) => Err(ContractError::MsgError {
            index: msg.id,
            error,
        }),
        SubMsgResult::Ok(res) => {
            collector[msg.id as usize] = Some(res);

            if msg.id + 1 == collector.len() as u64 {
                COLLECTOR.remove(deps.storage);
                let collector = collector
                    .into_iter()
                    .map(|res| res.unwrap())
                    .collect::<Vec<SubMsgResponse>>();
                Ok(Response::default()
                    .add_attribute("callbacks_processed", (msg.id + 1).to_string())
                    .set_data(ack_execute_success(
                        collector,
                        env.contract.address.into_string(),
                    )))
            } else {
                COLLECTOR.save(deps.storage, &collector)?;
                Ok(Response::default())
            }
        }
    }
}