variable-provider 0.2.2

variable provider smart contract
Documentation
use cosmwasm_std::{attr, Addr, Attribute, Deps, DepsMut, Response};
use rhaki_cw_plus::traits::IntoAddr;
use variable_provider_pkg::{
    definitions::Config,
    msgs::{RegisterVariableMsg, RemoveVariableMsg, UpdateOwnerMsg},
};

use crate::{
    response::{ContractError, ContractResponse, ContractResult},
    state::{CONFIG, VARIABLES},
};

pub fn run_register_variable(deps: DepsMut, msg: RegisterVariableMsg) -> ContractResponse {
    if let Ok(variable) = VARIABLES.load(deps.storage, msg.key.clone()) {
        return Err(ContractError::KeyAlredyRegistered {
            key: msg.key,
            value: variable,
        });
    }

    let validate = msg.value.clone().validate(deps.as_ref())?;

    VARIABLES.save(deps.storage, msg.key.clone(), &validate)?;

    Ok(Response::new()
        .add_attribute("action", "register_address")
        .add_attribute("key", msg.key)
        .add_attribute("value", format!("{:?}", msg.value)))
}

pub fn run_remove_variable(deps: DepsMut, msg: RemoveVariableMsg) -> ContractResponse {
    let variable = VARIABLES.load(deps.storage, msg.key.clone())?;

    VARIABLES.remove(deps.storage, msg.key.clone());

    Ok(Response::new()
        .add_attribute("action", "remove_address")
        .add_attribute("key", msg.key)
        .add_attribute("value", format!("{:?}", variable)))
}

pub fn run_update_owner_msg(deps: DepsMut, msg: UpdateOwnerMsg) -> ContractResponse {
    let mut config = CONFIG.load(deps.storage)?;

    let attrs = match (msg.add, msg.remove) {
        (None, None) => Err(ContractError::InvalidUpdateOwnerMsg),
        (None, Some(to_remove)) => remove_owners(deps.as_ref(), &mut config, to_remove),
        (Some(to_add), None) => add_owners(deps.as_ref(), &mut config, to_add),
        (Some(to_add), Some(to_remove)) => {
            let mut combined = vec![];
            combined.extend_from_slice(&add_owners(deps.as_ref(), &mut config, to_add)?);
            combined.extend_from_slice(&remove_owners(deps.as_ref(), &mut config, to_remove)?);
            Ok(combined)
        }
    }?;

    config.validate()?;

    CONFIG.save(deps.storage, &config)?;
    Ok(Response::new()
        .add_attribute("action", "update_owners")
        .add_attributes(attrs))
}

fn add_owners(
    deps: Deps,
    config: &mut Config,
    addresses: Vec<String>,
) -> ContractResult<Vec<Attribute>> {
    let mut attrs: Vec<Attribute> = vec![];

    for address in addresses {
        let address = address.into_addr(deps.api)?;

        if config.owners.contains(&address) {
            return Err(ContractError::IsAlredyOwner { addr: address });
        }

        attrs.push(attr("owner_added", address.clone()));

        config.owners.push(address)
    }

    Ok(attrs)
}

fn remove_owners(
    deps: Deps,
    config: &mut Config,
    addresses: Vec<String>,
) -> ContractResult<Vec<Attribute>> {
    let mut attrs: Vec<Attribute> = vec![];

    let addresses = addresses
        .into_iter()
        .map(|address| -> ContractResult<Addr> {
            let address = address.into_addr(deps.api)?;

            if !config.owners.contains(&address) {
                return Err(ContractError::IsNotOwner { addr: address });
            }

            attrs.push(attr("owner_removed", address.clone()));

            Ok(address)
        })
        .collect::<ContractResult<Vec<Addr>>>()?;

    config.owners = config
        .owners
        .clone()
        .into_iter()
        .filter(|val| !addresses.contains(val))
        .collect();

    Ok(attrs)
}