marbu-customization-module 0.2.0-alpha

Komple Framework module for marketplace customization in Marbu.
Documentation
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
    from_binary, to_binary, Binary, Deps, DepsMut, Env, MessageInfo, Order, Response, StdResult,
};
use cw2::set_contract_version;
use komple_framework_types::shared::query::ResponseWrapper;
use komple_framework_types::shared::RegisterMsg;
use komple_framework_utils::check_admin_privileges;
use komple_framework_utils::shared::execute_lock_execute;

use crate::error::ContractError;
use crate::msg::{ExecuteMsg, QueryMsg};
use crate::state::{Config, Data, CONFIG, DATA_MAP, EXECUTE_LOCK, HUB_ADDR};

// version info for migration info
const CONTRACT_NAME: &str = "crates.io:marbu-customization-module";
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: RegisterMsg,
) -> Result<Response, ContractError> {
    set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

    let admin = deps.api.addr_validate(&msg.admin)?;

    let config = Config { admin };
    CONFIG.save(deps.storage, &config)?;

    HUB_ADDR.save(deps.storage, &info.sender)?;

    EXECUTE_LOCK.save(deps.storage, &false)?;
    
    if let Some(data) = msg.data {
        let data: Vec<Data> = from_binary(&data)?;
    
        // Save the customization data
        for d in data {
            DATA_MAP.save(deps.storage, d.key, &d.value)?;
        }
    };

    /* TODO: Add events in here for indexing */
    Ok(Response::default())
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    let execute_lock = EXECUTE_LOCK.load(deps.storage)?;
    if execute_lock {
        return Err(ContractError::ExecuteLocked {});
    };

    match msg {
        ExecuteMsg::SetData { key, value } => execute_set_data(deps, env, info, key, value),
        ExecuteMsg::SetDataBatch { data } => execute_set_data_batch(deps, env, info, data),
        ExecuteMsg::LockExecute {} => {
            let res = execute_lock_execute(
                deps,
                info,
                "marbu_customization",
                &env.contract.address,
                EXECUTE_LOCK,
            );
            match res {
                Ok(res) => Ok(res),
                Err(err) => Err(err.into()),
            }
        }
    }
}

fn execute_set_data(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    key: String,
    value: Binary,
) -> Result<Response, ContractError> {
    let config = CONFIG.load(deps.storage)?;
    let hub_addr = HUB_ADDR.may_load(deps.storage)?;

    check_admin_privileges(
        &info.sender,
        &env.contract.address,
        &config.admin,
        hub_addr,
        None,
    )?;

    DATA_MAP.save(deps.storage, key, &value)?;

    /* TODO: Add events in here for indexing */
    Ok(Response::new().add_attribute("action", "set_data"))
}

fn execute_set_data_batch(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    data: Vec<Data>,
) -> Result<Response, ContractError> {
    let config = CONFIG.load(deps.storage)?;
    let hub_addr = HUB_ADDR.may_load(deps.storage)?;

    check_admin_privileges(
        &info.sender,
        &env.contract.address,
        &config.admin,
        hub_addr,
        None,
    )?;

    for d in data {
        DATA_MAP.save(deps.storage, d.key, &d.value)?;
    }

    /* TODO: Add events in here for indexing */
    Ok(Response::new().add_attribute("action", "set_data_batch"))
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, _env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::Config {} => to_binary(&query_config(deps)?),
        QueryMsg::GetData { key } => to_binary(&query_get_data(deps, key)?),
        QueryMsg::GetDataBatch { keys } => to_binary(&query_get_data_batch(deps, keys)?),
        QueryMsg::ListKeys {} => to_binary(&query_list_keys(deps)?),
    }
}

fn query_config(deps: Deps) -> StdResult<ResponseWrapper<Config>> {
    let config = CONFIG.load(deps.storage)?;
    Ok(ResponseWrapper::new("config", config))
}

fn query_get_data(deps: Deps, key: String) -> StdResult<ResponseWrapper<Option<Binary>>> {
    let data = DATA_MAP.may_load(deps.storage, key)?;
    Ok(ResponseWrapper::new("get_data", data))
}

fn query_get_data_batch(
    deps: Deps,
    keys: Vec<String>,
) -> StdResult<ResponseWrapper<Vec<Option<Binary>>>> {
    let mut all_data: Vec<Option<Binary>> = vec![];

    for key in keys {
        let data = DATA_MAP.may_load(deps.storage, key)?;
        all_data.push(data);
    }

    Ok(ResponseWrapper::new("get_data", all_data))
}

fn query_list_keys(deps: Deps) -> StdResult<ResponseWrapper<Vec<String>>> {
    let keys = DATA_MAP
        .keys(deps.storage, None, None, Order::Ascending)
        .map(|item| {
            let key = item.unwrap();
            key
        })
        .collect::<Vec<String>>();

    Ok(ResponseWrapper::new("list_keys", keys))
}