contract-utils 0.1.0

A package for Test env
use casper_contract::{
    contract_api::{runtime, storage},
    unwrap_or_revert::UnwrapOrRevert,
};
use casper_types::{ApiError, Key};

use crate::{ContractContext, ContractStorage, Dict};

const ADMINS_DICT: &str = "admins";

pub trait AdminControl<Storage: ContractStorage>: ContractContext<Storage> {
    fn init(&mut self) {
        Admins::init();
    }

    fn add_admin(&mut self, address: Key) {
        self.assert_caller_is_admin();
        self.add_admin_without_checked(address);
    }

    fn disable_admin(&mut self, address: Key) {
        self.assert_caller_is_admin();
        Admins::instance().disable_admin(&address);
    }

    fn add_admin_without_checked(&mut self, address: Key) {
        Admins::instance().add_admin(&address);
    }

    fn assert_caller_is_admin(&self) {
        let caller = self.get_caller();
        if !Admins::instance().is_admin(&caller) {
            runtime::revert(ApiError::User(20));
        }
    }
}

struct Admins {
    dict: Dict,
}

impl Admins {
    pub fn instance() -> Admins {
        Admins {
            dict: Dict::instance(ADMINS_DICT),
        }
    }
    pub fn init() {
        storage::new_dictionary(ADMINS_DICT).unwrap_or_revert();
    }

    pub fn is_admin(&self, key: &Key) -> bool {
        self.dict.get_by_key::<()>(key).is_some()
    }

    pub fn add_admin(&self, key: &Key) {
        self.dict.set_by_key(key, ());
    }

    pub fn disable_admin(&self, key: &Key) {
        self.dict.remove_by_key::<()>(key);
    }
}