use std::ops::{Div, Mul, Sub};

#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
    ensure, to_json_binary, Addr, BankMsg, Binary, Coin, CosmosMsg, Decimal, Deps, DepsMut, Env,
    MessageInfo, Order, StdResult, Storage, Uint128,
};
use cw2::{get_contract_version, set_contract_version, ContractVersion};
use cw_storage_plus::Bound;
use cyber_std::types::{Load, Trigger};
use cyber_std::{CyberMsg, Response};

use crate::block_step::block_step;
use crate::delegate_info::{get_delegate, get_delegated, get_delegates};
use crate::error::ContractError;
use crate::msg::{EconomyData, ExecuteMsg, InstantiateMsg, MigrateMsg, QueryMsg, SudoMsg};
use crate::neuron_info::{get_neuron, get_neuron_lite, get_neurons, get_neurons_lite};
use crate::registration::{do_burned_registration, do_registration, do_sudo_registration};
use crate::root::{do_root_register, get_network_lock_cost, user_add_network, user_remove_network};
use crate::serving::{do_serve_axon, do_serve_prometheus};
use crate::stake_info::{get_stake_info_for_coldkey, get_stake_info_for_coldkeys};
use crate::staking::{
    do_add_stake, do_become_delegate, do_remove_stake, do_set_delegate_commission,
};
use crate::state::{
    AxonInfo, Metadata, PrometheusInfo, ACTIVE, ACTIVITY_CUTOFF, ADJUSTMENTS_ALPHA,
    ADJUSTMENT_INTERVAL, ALLOW_FAUCET, AXONS, BLOCKS_SINCE_LAST_STEP, BLOCK_EMISSION,
    BONDS_MOVING_AVERAGE, BURN, BURN_REGISTRATIONS_THIS_INTERVAL, COMMISSION_CHANGE, CONSENSUS,
    DEFAULT_TAKE, DELEGATES, DENOM, DIFFICULTY, DIVIDENDS, EMISSION, EMISSION_VALUES,
    IMMUNITY_PERIOD, INCENTIVE, KAPPA, LAST_ADJUSTMENT_BLOCK, LAST_UPDATE, MAX_ALLOWED_UIDS,
    MAX_ALLOWED_VALIDATORS, MAX_BURN, MAX_DIFFICULTY, MAX_REGISTRATION_PER_BLOCK,
    MAX_WEIGHTS_LIMIT, MIN_ALLOWED_WEIGHTS, MIN_BURN, MIN_DIFFICULTY, NETWORKS_ADDED,
    NETWORKS_METADATA, NETWORK_IMMUNITY_PERIOD, NETWORK_LAST_LOCK_COST, NETWORK_LAST_REGISTERED,
    NETWORK_LOCK_REDUCTION_INTERVAL, NETWORK_MIN_LOCK_COST, NETWORK_MODALITY, NETWORK_RATE_LIMIT,
    NETWORK_REGISTERED_AT, NETWORK_REGISTRATION_ALLOWED, OWNER, PENDING_EMISSION,
    POW_REGISTRATIONS_THIS_INTERVAL, PROMETHEUS, PRUNING_SCORES, RANK,
    RAO_RECYCLED_FOR_REGISTRATION, REGISTRATIONS_THIS_BLOCK, REGISTRATIONS_THIS_INTERVAL, RHO,
    ROOT, SERVING_RATE_LIMIT, STAKE, SUBNETWORK_N, SUBNET_LIMIT, SUBNET_LOCKED, SUBNET_OWNER,
    SUBNET_OWNER_CUT, TARGET_REGISTRATIONS_PER_INTERVAL, TEMPO, TOTAL_COLDKEY_STAKE,
    TOTAL_HOTKEY_STAKE, TOTAL_ISSUANCE, TOTAL_NETWORKS, TOTAL_REWARDS, TOTAL_STAKE, TRUST,
    TX_RATE_LIMIT, UIDS, VALIDATOR_PERMIT, VALIDATOR_TRUST, VERSE_METADATA, WEIGHTS_SET_RATE_LIMIT,
    WEIGHTS_VERSION_KEY,
};
use crate::state_info::get_state_info;
use crate::subnet_info::{get_subnet_hyperparams, get_subnet_info, get_subnets_info};
use crate::uids::get_registered_networks_for_hotkey;
use crate::utils::{
    do_sudo_set_activity_cutoff, do_sudo_set_adjustment_alpha, do_sudo_set_adjustment_interval,
    do_sudo_set_block_emission, do_sudo_set_bonds_moving_average, do_sudo_set_commission_change,
    do_sudo_set_default_take, do_sudo_set_difficulty, do_sudo_set_immunity_period,
    do_sudo_set_kappa, do_sudo_set_lock_reduction_interval, do_sudo_set_max_allowed_uids,
    do_sudo_set_max_allowed_validators, do_sudo_set_max_burn, do_sudo_set_max_difficulty,
    do_sudo_set_max_registrations_per_block, do_sudo_set_max_weight_limit,
    do_sudo_set_min_allowed_weights, do_sudo_set_min_burn, do_sudo_set_min_difficulty,
    do_sudo_set_network_immunity_period, do_sudo_set_network_min_lock_cost,
    do_sudo_set_network_rate_limit, do_sudo_set_network_registration_allowed,
    do_sudo_set_rao_recycled, do_sudo_set_rho, do_sudo_set_root, do_sudo_set_serving_rate_limit,
    do_sudo_set_subnet_limit, do_sudo_set_subnet_metadata, do_sudo_set_subnet_owner,
    do_sudo_set_subnet_owner_cut, do_sudo_set_target_registrations_per_interval, do_sudo_set_tempo,
    do_sudo_set_total_issuance, do_sudo_set_tx_rate_limit, do_sudo_set_validator_permit_for_uid,
    do_sudo_set_validator_prune_len, do_sudo_set_verse_metadata,
    do_sudo_set_weights_set_rate_limit, do_sudo_set_weights_version_key, do_sudo_unstake_all,
    ensure_root,
};
use crate::weights::{do_set_weights, get_network_weights, get_network_weights_sparse};

const CONTRACT_NAME: &str = "cybernet";
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)?;

    ROOT.save(deps.storage, &info.sender)?;
    ALLOW_FAUCET.save(deps.storage, &false)?;

    // denom which sent during instantiate is general denom for contract
    ensure!(info.funds.len() == 1, ContractError::DenomSetError {});
    DENOM.save(deps.storage, &info.funds[0].denom)?;
    COMMISSION_CHANGE.save(deps.storage, &false)?;

    TOTAL_ISSUANCE.save(deps.storage, &0)?;
    TOTAL_STAKE.save(deps.storage, &0)?;

    // -- Cybertensor parameters initialization --

    SUBNET_LIMIT.save(deps.storage, &16)?;
    NETWORK_IMMUNITY_PERIOD.save(deps.storage, &14400)?;
    BLOCK_EMISSION.save(deps.storage, &4_200_000)?;

    SUBNET_OWNER_CUT.save(deps.storage, &0)?;
    NETWORK_RATE_LIMIT.save(deps.storage, &0)?;

    // 20% (113108/2^16)
    DEFAULT_TAKE.save(deps.storage, &13107)?;
    TX_RATE_LIMIT.save(deps.storage, &0)?;

    NETWORK_LAST_LOCK_COST.save(deps.storage, &10_000_000_000)?;
    NETWORK_MIN_LOCK_COST.save(deps.storage, &10_000_000_000)?;
    NETWORK_LOCK_REDUCTION_INTERVAL.save(deps.storage, &(7 * 14400))?;
    TOTAL_REWARDS.save(deps.storage, &0)?;

    // -- Root network initialization --
    let root_netuid: u16 = 0;

    SUBNET_OWNER.save(deps.storage, root_netuid, &info.sender)?;
    SUBNETWORK_N.save(deps.storage, root_netuid, &0)?;
    NETWORKS_ADDED.save(deps.storage, root_netuid, &true)?;
    NETWORK_MODALITY.save(deps.storage, root_netuid, &u16::MAX)?; // revisit
    MAX_ALLOWED_UIDS.save(deps.storage, root_netuid, &64)?;
    MAX_ALLOWED_VALIDATORS.save(deps.storage, root_netuid, &64)?;
    MIN_ALLOWED_WEIGHTS.save(deps.storage, root_netuid, &1)?;
    MAX_WEIGHTS_LIMIT.save(deps.storage, root_netuid, &u16::MAX)?;
    TEMPO.save(deps.storage, root_netuid, &1)?;
    NETWORK_REGISTRATION_ALLOWED.save(deps.storage, root_netuid, &true)?;
    TARGET_REGISTRATIONS_PER_INTERVAL.save(deps.storage, root_netuid, &1)?;
    WEIGHTS_VERSION_KEY.save(deps.storage, root_netuid, &0)?;
    NETWORK_REGISTERED_AT.save(deps.storage, root_netuid, &env.block.height)?;
    WEIGHTS_SET_RATE_LIMIT.save(deps.storage, root_netuid, &100)?;

    PENDING_EMISSION.save(deps.storage, root_netuid, &0)?;
    BLOCKS_SINCE_LAST_STEP.save(deps.storage, root_netuid, &0)?;
    BONDS_MOVING_AVERAGE.save(deps.storage, root_netuid, &900_000)?;
    LAST_ADJUSTMENT_BLOCK.save(deps.storage, root_netuid, &0)?;
    ADJUSTMENT_INTERVAL.save(deps.storage, root_netuid, &100)?;
    BURN.save(deps.storage, root_netuid, &1_000_000_000)?;
    MIN_BURN.save(deps.storage, root_netuid, &100_000_000)?;
    MAX_BURN.save(deps.storage, root_netuid, &100_000_000_000)?;
    REGISTRATIONS_THIS_BLOCK.save(deps.storage, root_netuid, &0)?;
    MAX_REGISTRATION_PER_BLOCK.save(deps.storage, root_netuid, &1)?;
    REGISTRATIONS_THIS_INTERVAL.save(deps.storage, root_netuid, &0)?;
    KAPPA.save(deps.storage, root_netuid, &32_767)?;
    RHO.save(deps.storage, root_netuid, &30)?;
    RAO_RECYCLED_FOR_REGISTRATION.save(deps.storage, root_netuid, &0)?;
    ACTIVITY_CUTOFF.save(deps.storage, root_netuid, &14400)?;
    SERVING_RATE_LIMIT.save(deps.storage, root_netuid, &50)?;
    DIFFICULTY.save(deps.storage, root_netuid, &10_000_000)?;
    IMMUNITY_PERIOD.save(deps.storage, root_netuid, &14400)?;
    POW_REGISTRATIONS_THIS_INTERVAL.save(deps.storage, root_netuid, &0)?;
    BURN_REGISTRATIONS_THIS_INTERVAL.save(deps.storage, root_netuid, &0)?;
    ADJUSTMENTS_ALPHA.save(deps.storage, root_netuid, &0)?;
    MIN_DIFFICULTY.save(deps.storage, root_netuid, &1)?;
    MAX_DIFFICULTY.save(deps.storage, root_netuid, &1000000)?;
    EMISSION_VALUES.save(deps.storage, root_netuid, &0)?;
    NETWORK_LAST_REGISTERED.save(deps.storage, &0)?;
    TOTAL_NETWORKS.save(deps.storage, &1)?;
    NETWORKS_METADATA.save(
        deps.storage,
        root_netuid,
        &Metadata {
            name: "root".to_string(),
            particle: "Qmd2anGbDQj7pYWMZwv9SEw11QFLQu3nzoGXfi1KwLy3Zr".to_string(),
            description: "Qmd2anGbDQj7pYWMZwv9SEw11QFLQu3nzoGXfi1KwLy3Zr".to_string(),
            logo: "".to_string(),
            types: "".to_string(),
            extra: "".to_string(),
        },
    )?;

    // -- Subnetwork 1 initialization --
    let netuid: u16 = 1;

    SUBNET_OWNER.save(deps.storage, netuid, &info.sender)?;
    NETWORKS_ADDED.save(deps.storage, netuid, &true)?;
    TEMPO.save(deps.storage, netuid, &10)?;
    NETWORK_MODALITY.save(deps.storage, netuid, &0)?;
    KAPPA.save(deps.storage, netuid, &0)?;
    DIFFICULTY.save(deps.storage, netuid, &10_000_000)?;
    IMMUNITY_PERIOD.save(deps.storage, netuid, &14400)?;
    ACTIVITY_CUTOFF.save(deps.storage, netuid, &14400)?;
    EMISSION_VALUES.save(deps.storage, netuid, &0)?;
    MAX_WEIGHTS_LIMIT.save(deps.storage, netuid, &u16::MAX)?;
    MIN_ALLOWED_WEIGHTS.save(deps.storage, netuid, &0)?;
    REGISTRATIONS_THIS_INTERVAL.save(deps.storage, netuid, &0)?;
    POW_REGISTRATIONS_THIS_INTERVAL.save(deps.storage, netuid, &0)?;
    BURN_REGISTRATIONS_THIS_INTERVAL.save(deps.storage, netuid, &0)?;
    MAX_ALLOWED_VALIDATORS.save(deps.storage, netuid, &32)?;
    MAX_ALLOWED_UIDS.save(deps.storage, netuid, &128)?;
    WEIGHTS_VERSION_KEY.save(deps.storage, netuid, &0)?;
    WEIGHTS_SET_RATE_LIMIT.save(deps.storage, netuid, &100)?;

    PENDING_EMISSION.save(deps.storage, netuid, &0)?;
    BLOCKS_SINCE_LAST_STEP.save(deps.storage, netuid, &0)?;
    BONDS_MOVING_AVERAGE.save(deps.storage, netuid, &900_000)?;
    LAST_ADJUSTMENT_BLOCK.save(deps.storage, netuid, &0)?;
    ADJUSTMENT_INTERVAL.save(deps.storage, netuid, &100)?;
    BURN.save(deps.storage, netuid, &1_000_000_000)?;
    MIN_BURN.save(deps.storage, netuid, &100_000_000)?;
    MAX_BURN.save(deps.storage, netuid, &100_000_000_000)?;
    REGISTRATIONS_THIS_BLOCK.save(deps.storage, netuid, &0)?;
    MAX_REGISTRATION_PER_BLOCK.save(deps.storage, netuid, &3)?;
    KAPPA.save(deps.storage, netuid, &32_767)?;
    RHO.save(deps.storage, netuid, &30)?;
    RAO_RECYCLED_FOR_REGISTRATION.save(deps.storage, netuid, &0)?;
    SERVING_RATE_LIMIT.save(deps.storage, netuid, &50)?;
    ADJUSTMENTS_ALPHA.save(deps.storage, netuid, &0)?;
    MIN_DIFFICULTY.save(deps.storage, netuid, &1)?;
    MAX_DIFFICULTY.save(deps.storage, netuid, &1000000)?;
    SUBNET_LOCKED.save(deps.storage, netuid, &0)?;
    NETWORK_REGISTERED_AT.save(deps.storage, netuid, &env.block.height)?;
    SUBNETWORK_N.save(deps.storage, netuid, &0)?;
    TARGET_REGISTRATIONS_PER_INTERVAL.save(deps.storage, netuid, &1)?;
    NETWORK_REGISTRATION_ALLOWED.save(deps.storage, netuid, &true)?;
    NETWORKS_METADATA.save(
        deps.storage,
        netuid,
        &Metadata {
            name: "x".to_string(),
            particle: "Qmd2anGbDQj7pYWMZwv9SEw11QFLQu3nzoGXfi1KwLy3Zr".to_string(),
            description: "Qmd2anGbDQj7pYWMZwv9SEw11QFLQu3nzoGXfi1KwLy3Zr".to_string(),
            logo: "".to_string(),
            types: "".to_string(),
            extra: "".to_string(),
        },
    )?;

    RANK.save(deps.storage, netuid, &vec![])?;
    TRUST.save(deps.storage, netuid, &vec![])?;
    ACTIVE.save(deps.storage, netuid, &vec![])?;
    EMISSION.save(deps.storage, netuid, &vec![])?;
    CONSENSUS.save(deps.storage, netuid, &vec![])?;
    INCENTIVE.save(deps.storage, netuid, &vec![])?;
    DIVIDENDS.save(deps.storage, netuid, &vec![])?;
    LAST_UPDATE.save(deps.storage, netuid, &vec![])?;
    PRUNING_SCORES.save(deps.storage, netuid, &vec![])?;
    VALIDATOR_TRUST.save(deps.storage, netuid, &vec![])?;
    VALIDATOR_PERMIT.save(deps.storage, netuid, &vec![])?;

    TOTAL_NETWORKS.update(deps.storage, |mut n| -> StdResult<_> {
        n += 1;
        Ok(n)
    })?;

    Ok(Response::default().add_attribute("action", "instantiate"))
}

pub fn activate(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
    ensure_root(deps.storage, &info.sender)?;

    let denom = DENOM.load(deps.storage)?;
    let res = Response::new()
        .add_message(CyberMsg::creat_thought(
            env.contract.address.to_string(),
            Trigger {
                period: Some(1),
                block: Some(0),
            },
            Load {
                // {"block_step":{}}
                input: "eyJibG9ja19zdGVwIjp7fX0=".to_string(),
                gas_price: Coin {
                    denom: denom.to_string(),
                    amount: Uint128::from(10u128),
                },
            },
            env.contract.address.as_str()[0..32].to_string(),
            "Qmd2anGbDQj7pYWMZwv9SEw11QFLQu3nzoGXfi1KwLy3Zr".to_string(),
        ))
        .add_attribute("action", "activate");

    Ok(res)
}

pub fn deactivate(deps: DepsMut, env: Env, info: MessageInfo) -> Result<Response, ContractError> {
    ensure_root(deps.storage, &info.sender)?;

    let denom = DENOM.load(deps.storage)?;
    let root = ROOT.load(deps.storage)?;

    let contract_balance = deps
        .querier
        .query_balance(env.clone().contract.address, denom.clone())?;
    let total_stake = TOTAL_STAKE.load(deps.storage)?;

    let return_rewards_msg = CosmosMsg::Bank(BankMsg::Send {
        to_address: root.to_string(),
        amount: vec![Coin {
            denom,
            amount: contract_balance.amount.sub(Uint128::from(total_stake)),
        }],
    });

    let disable_dmn = CyberMsg::forget_thought(
        env.contract.address.to_string(),
        env.contract.address.as_str()[0..32].to_string(),
    );

    let res = Response::new()
        .add_message(return_rewards_msg)
        .add_message(disable_dmn)
        .add_attribute("action", "deactivate");

    Ok(res)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn execute(
    deps: DepsMut,
    env: Env,
    info: MessageInfo,
    msg: ExecuteMsg,
) -> Result<Response, ContractError> {
    match msg {
        ExecuteMsg::Activate {} => activate(deps, env, info),
        ExecuteMsg::Deactivate {} => deactivate(deps, env, info),
        ExecuteMsg::BlockStep {} => block_step(deps, env, Some(info.sender)),
        ExecuteMsg::SetWeights {
            netuid,
            dests,
            weights,
            version_key,
        } => do_set_weights(deps, env, info, netuid, dests, weights, version_key),
        ExecuteMsg::BecomeDelegate { hotkey } => do_become_delegate(deps, env, info, hotkey),
        ExecuteMsg::AddStake { hotkey } => do_add_stake(deps, env, info, hotkey),
        ExecuteMsg::RemoveStake { hotkey, amount } => {
            do_remove_stake(deps, env, info, hotkey, amount)
        }
        ExecuteMsg::SetDelegateCommission { hotkey, commission } => {
            do_set_delegate_commission(deps, env, info, hotkey, commission)
        }
        ExecuteMsg::ServeAxon {
            netuid,
            version,
            ip,
            port,
            ip_type,
            protocol,
            placeholder1,
            placeholder2,
        } => do_serve_axon(
            deps,
            env,
            info,
            netuid,
            version,
            ip,
            port,
            ip_type,
            protocol,
            placeholder1,
            placeholder2,
        ),
        ExecuteMsg::ServePrometheus {
            netuid,
            version,
            ip,
            port,
            ip_type,
        } => do_serve_prometheus(deps, env, info, netuid, version, ip, port, ip_type),
        ExecuteMsg::Register {
            netuid,
            block_number,
            nonce,
            work,
            hotkey,
            coldkey,
        } => do_registration(
            deps,
            env,
            info,
            netuid,
            block_number,
            nonce,
            work,
            hotkey,
            coldkey,
        ),
        ExecuteMsg::RootRegister { hotkey } => do_root_register(deps, env, info, hotkey),
        ExecuteMsg::BurnedRegister { netuid, hotkey } => {
            do_burned_registration(deps, env, info, netuid, hotkey)
        }

        ExecuteMsg::RegisterNetwork {} => user_add_network(deps, env, info),
        ExecuteMsg::DissolveNetwork { netuid } => user_remove_network(deps, env, info, netuid),
        // ExecuteMsg::Faucet { block_number, nonce, work } => do_faucet(deps, env, info, block_number, nonce, work),
        ExecuteMsg::SudoRegister {
            netuid,
            hotkey,
            coldkey,
        } => do_sudo_registration(deps, env, info, netuid, hotkey, coldkey),
        ExecuteMsg::SudoSetDefaultTake { default_take } => {
            do_sudo_set_default_take(deps, env, info, default_take)
        }
        ExecuteMsg::SudoSetServingRateLimit {
            netuid,
            serving_rate_limit,
        } => do_sudo_set_serving_rate_limit(deps, env, info, netuid, serving_rate_limit),
        ExecuteMsg::SudoSetTxRateLimit { tx_rate_limit } => {
            do_sudo_set_tx_rate_limit(deps, env, info, tx_rate_limit)
        }
        ExecuteMsg::SudoSetMaxBurn { netuid, max_burn } => {
            do_sudo_set_max_burn(deps, env, info, netuid, max_burn)
        }
        ExecuteMsg::SudoSetMinBurn { netuid, min_burn } => {
            do_sudo_set_min_burn(deps, env, info, netuid, min_burn)
        }
        ExecuteMsg::SudoSetMaxDifficulty {
            netuid,
            max_difficulty,
        } => do_sudo_set_max_difficulty(deps, env, info, netuid, max_difficulty),
        ExecuteMsg::SudoSetMinDifficulty {
            netuid,
            min_difficulty,
        } => do_sudo_set_min_difficulty(deps, env, info, netuid, min_difficulty),
        ExecuteMsg::SudoSetWeightsSetRateLimit {
            netuid,
            weights_set_rate_limit,
        } => do_sudo_set_weights_set_rate_limit(deps, env, info, netuid, weights_set_rate_limit),
        ExecuteMsg::SudoSetWeightsVersionKey {
            netuid,
            weights_version_key,
        } => do_sudo_set_weights_version_key(deps, env, info, netuid, weights_version_key),
        ExecuteMsg::SudoSetBondsMovingAverage {
            netuid,
            bonds_moving_average,
        } => do_sudo_set_bonds_moving_average(deps, env, info, netuid, bonds_moving_average),
        ExecuteMsg::SudoSetMaxAllowedValidators {
            netuid,
            max_allowed_validators,
        } => do_sudo_set_max_allowed_validators(deps, env, info, netuid, max_allowed_validators),
        ExecuteMsg::SudoSetDifficulty { netuid, difficulty } => {
            do_sudo_set_difficulty(deps, env, info, netuid, difficulty)
        }
        ExecuteMsg::SudoSetAdjustmentInterval {
            netuid,
            adjustment_interval,
        } => do_sudo_set_adjustment_interval(deps, env, info, netuid, adjustment_interval),
        ExecuteMsg::SudoSetTargetRegistrationsPerInterval {
            netuid,
            target_registrations_per_interval,
        } => do_sudo_set_target_registrations_per_interval(
            deps,
            env,
            info,
            netuid,
            target_registrations_per_interval,
        ),
        ExecuteMsg::SudoSetActivityCutoff {
            netuid,
            activity_cutoff,
        } => do_sudo_set_activity_cutoff(deps, env, info, netuid, activity_cutoff),
        ExecuteMsg::SudoSetRho { netuid, rho } => do_sudo_set_rho(deps, env, info, netuid, rho),
        ExecuteMsg::SudoSetKappa { netuid, kappa } => {
            do_sudo_set_kappa(deps, env, info, netuid, kappa)
        }
        ExecuteMsg::SudoSetMaxAllowedUids {
            netuid,
            max_allowed_uids,
        } => do_sudo_set_max_allowed_uids(deps, env, info, netuid, max_allowed_uids),
        ExecuteMsg::SudoSetMinAllowedWeights {
            netuid,
            min_allowed_weights,
        } => do_sudo_set_min_allowed_weights(deps, env, info, netuid, min_allowed_weights),
        ExecuteMsg::SudoSetValidatorPruneLen {
            netuid,
            validator_prune_len,
        } => do_sudo_set_validator_prune_len(deps, env, info, netuid, validator_prune_len),
        ExecuteMsg::SudoSetImmunityPeriod {
            netuid,
            immunity_period,
        } => do_sudo_set_immunity_period(deps, env, info, netuid, immunity_period),
        ExecuteMsg::SudoSetMaxWeightLimit {
            netuid,
            max_weight_limit,
        } => do_sudo_set_max_weight_limit(deps, env, info, netuid, max_weight_limit),
        ExecuteMsg::SudoSetMaxRegistrationsPerBlock {
            netuid,
            max_registrations_per_block,
        } => do_sudo_set_max_registrations_per_block(
            deps,
            env,
            info,
            netuid,
            max_registrations_per_block,
        ),
        ExecuteMsg::SudoSetTotalIssuance { total_issuance } => {
            do_sudo_set_total_issuance(deps, env, info, total_issuance)
        }
        ExecuteMsg::SudoSetTempo { netuid, tempo } => {
            do_sudo_set_tempo(deps, env, info, netuid, tempo)
        }
        ExecuteMsg::SudoSetRaoRecycled {
            netuid,
            rao_recycled,
        } => do_sudo_set_rao_recycled(deps, env, info, netuid, rao_recycled),
        // ExecuteMsg::Sudo { .. } => {}
        ExecuteMsg::SudoSetRegistrationAllowed {
            netuid,
            registration_allowed,
        } => {
            do_sudo_set_network_registration_allowed(deps, env, info, netuid, registration_allowed)
        }
        ExecuteMsg::SudoSetAdjustmentAlpha {
            netuid,
            adjustment_alpha,
        } => do_sudo_set_adjustment_alpha(deps, env, info, netuid, adjustment_alpha),
        ExecuteMsg::SudoSetSubnetOwnerCut { cut } => {
            do_sudo_set_subnet_owner_cut(deps, env, info, cut)
        }
        ExecuteMsg::SudoSetNetworkRateLimit { rate_limit } => {
            do_sudo_set_network_rate_limit(deps, env, info, rate_limit)
        }
        ExecuteMsg::SudoSetNetworkImmunityPeriod { immunity_period } => {
            do_sudo_set_network_immunity_period(deps, env, info, immunity_period)
        }
        ExecuteMsg::SudoSetNetworkMinLockCost { lock_cost } => {
            do_sudo_set_network_min_lock_cost(deps, env, info, lock_cost)
        }
        ExecuteMsg::SudoSetSubnetLimit { max_subnets } => {
            do_sudo_set_subnet_limit(deps, env, info, max_subnets)
        }
        ExecuteMsg::SudoSetLockReductionInterval { interval } => {
            do_sudo_set_lock_reduction_interval(deps, env, info, interval)
        }
        ExecuteMsg::SudoSetValidatorPermitForUid {
            netuid,
            uid,
            permit,
        } => do_sudo_set_validator_permit_for_uid(deps, env, info, netuid, uid, permit),
        ExecuteMsg::SudoSetBlockEmission { emission } => {
            do_sudo_set_block_emission(deps, env, info, emission)
        }
        ExecuteMsg::SudoSetSubnetMetadata { netuid, metadata } => {
            do_sudo_set_subnet_metadata(deps, env, info, netuid, metadata)
        }
        ExecuteMsg::SudoSetSubnetOwner { netuid, new_owner } => {
            do_sudo_set_subnet_owner(deps, env, info, netuid, new_owner)
        }
        ExecuteMsg::SudoSetRoot { new_root } => do_sudo_set_root(deps, env, info, new_root),
        ExecuteMsg::SudoSetVerseMetadata { metadata } => {
            do_sudo_set_verse_metadata(deps, env, info, metadata)
        }
        ExecuteMsg::SudoUnstakeAll { limit } => do_sudo_unstake_all(deps, env, info, limit),
        ExecuteMsg::SudoSetCommissionChange { change } => {
            do_sudo_set_commission_change(deps, env, info, change)
        }
    }
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn sudo(deps: DepsMut, env: Env, msg: SudoMsg) -> Result<Response, ContractError> {
    match msg {
        SudoMsg::BlockStep {} => block_step(deps, env, None),
    }
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
    match msg {
        QueryMsg::GetDelegates { start_after, limit } => {
            to_json_binary(&get_delegates(deps, start_after, limit)?)
        }
        QueryMsg::GetDelegate { delegate } => to_json_binary(&get_delegate(deps, delegate)?),
        QueryMsg::GetDelegated {
            delegatee,
            start_after,
            limit,
        } => to_json_binary(&get_delegated(deps, delegatee, start_after, limit)?),
        QueryMsg::GetNeuronsLite { netuid } => {
            to_json_binary(&get_neurons_lite(deps.storage, netuid)?)
        }
        QueryMsg::GetNeuronLite { netuid, uid } => {
            to_json_binary(&get_neuron_lite(deps.storage, netuid, uid)?)
        }
        QueryMsg::GetNeurons { netuid } => to_json_binary(&get_neurons(deps.storage, netuid)?),
        QueryMsg::GetNeuron { netuid, uid } => {
            to_json_binary(&get_neuron(deps.storage, netuid, uid)?)
        }
        QueryMsg::GetSubnetInfo { netuid } => to_json_binary(&get_subnet_info(deps, netuid)?),
        QueryMsg::GetSubnetsInfo {} => to_json_binary(&get_subnets_info(deps)?),
        QueryMsg::GetSubnetHyperparams { netuid } => {
            to_json_binary(&get_subnet_hyperparams(deps, netuid)?)
        }
        QueryMsg::GetStakeInfoForColdkey { coldkey } => {
            to_json_binary(&get_stake_info_for_coldkey(deps, coldkey)?)
        }
        QueryMsg::GetStakeInfoForColdkeys { coldkeys } => {
            to_json_binary(&get_stake_info_for_coldkeys(deps, coldkeys)?)
        }
        QueryMsg::GetNetworkRegistrationCost {} => to_json_binary(&get_network_lock_cost(
            deps.storage,
            deps.api,
            env.block.height,
        )?),

        QueryMsg::GetSubnetOwner { netuid } => {
            to_json_binary(&get_subnet_owner(deps.storage, netuid)?)
        }
        QueryMsg::GetHotkeyOwner { hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&get_hotkey_owner(deps.storage, &hotkey_address)?)
        }
        QueryMsg::GetStakeForColdkeyAndHotkey { coldkey, hotkey } => {
            let coldkey_address = deps.api.addr_validate(&coldkey)?;
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_stake_for_coldkey_and_hotkey(
                deps.storage,
                &hotkey_address,
                &coldkey_address,
            )?)
        }
        QueryMsg::GetUidForHotkeyOnSubnet { hotkey, netuid } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_uid_for_hotkey_on_subnet(
                deps.storage,
                &hotkey_address,
                netuid,
            )?)
        }
        QueryMsg::GetSubnetExist { netuid } => {
            to_json_binary(&query_subnet_exist(deps.storage, netuid)?)
        }
        QueryMsg::GetMaxWeightLimit { netuid } => {
            to_json_binary(&query_max_weight_limit(deps.storage, netuid)?)
        }
        QueryMsg::GetMinAllowedWeights { netuid } => {
            to_json_binary(&query_min_allowed_weights(deps.storage, netuid)?)
        }
        QueryMsg::GetDelegateTake { hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_delegate_take(deps.storage, &hotkey_address)?)
        }
        QueryMsg::GetBurn { netuid } => to_json_binary(&query_burn(deps.storage, netuid)?),
        QueryMsg::GetDifficulty { netuid } => {
            to_json_binary(&query_difficulty(deps.storage, netuid)?)
        }
        QueryMsg::GetTempo { netuid } => to_json_binary(&query_tempo(deps.storage, netuid)?),
        QueryMsg::GetTotalNetworks {} => to_json_binary(&query_total_networks(deps.storage)?),
        QueryMsg::GetNetworksAdded {} => to_json_binary(&query_networks_added(deps.storage)?),
        QueryMsg::GetEmissionValueBySubnet { netuid } => {
            to_json_binary(&query_emission_value_by_subnet(deps, netuid)?)
        }
        QueryMsg::GetAllSubnetNetuids {} => {
            to_json_binary(&query_all_subnet_netuids(deps.storage)?)
        }
        QueryMsg::GetNetuidsForHotkey { hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_netuids_for_hotkey(deps.storage, &hotkey_address)?)
        }
        QueryMsg::GetTotalIssuance {} => to_json_binary(&query_total_issuance(deps.storage)?),
        QueryMsg::GetTotalStake {} => to_json_binary(&query_total_stake(deps.storage)?),
        QueryMsg::GetTxRateLimit {} => to_json_binary(&query_tx_rate_limit(deps.storage)?),

        QueryMsg::GetAxonInfo { netuid, hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_get_axon_info(deps.storage, netuid, &hotkey_address)?)
        }
        QueryMsg::GetPrometheusInfo { netuid, hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_get_prometheus_info(
                deps.storage,
                netuid,
                &hotkey_address,
            )?)
        }
        QueryMsg::GetTotalStakeForHotkey { address } => {
            let hotkey_address = deps.api.addr_validate(&address)?;
            to_json_binary(&query_get_total_stake_for_hotkey(
                deps.storage,
                &hotkey_address,
            )?)
        }
        QueryMsg::GetTotalStakeForColdkey { address } => {
            let hotkey_address = deps.api.addr_validate(&address)?;
            to_json_binary(&query_get_total_stake_for_coldkey(
                deps.storage,
                &hotkey_address,
            )?)
        }
        QueryMsg::GetHotkeyExist { hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_get_hotkey_exist(deps.storage, &hotkey_address)?)
        }
        QueryMsg::GetStake { hotkey } => {
            let hotkey_address = deps.api.addr_validate(&hotkey)?;
            to_json_binary(&query_get_stake(deps.storage, &hotkey_address)?)
        }

        QueryMsg::GetState {} => to_json_binary(&get_state_info(deps.storage)?),
        QueryMsg::GetWeights { netuid } => {
            to_json_binary(&get_network_weights(deps.storage, netuid)?)
        }
        QueryMsg::GetWeightsSparse { netuid } => {
            to_json_binary(&get_network_weights_sparse(deps.storage, netuid)?)
        }
        QueryMsg::GetBlockRewards {} => to_json_binary(&get_block_rewards(deps.storage)?),
        QueryMsg::GetSubnetMetadata { netuid } => {
            to_json_binary(&get_subnet_metadata(deps.storage, netuid)?)
        }
        QueryMsg::GetSubnetsMetadata { start_after, limit } => {
            to_json_binary(&get_subnets_metadata(deps.storage, start_after, limit)?)
        }
        QueryMsg::GetVerseMetadata {} => to_json_binary(&get_verse_metadata(deps.storage)?),
        QueryMsg::GetEconomy {} => to_json_binary(&get_economy(deps.storage)?),
    }
}

pub fn get_subnet_owner(store: &dyn Storage, netuid: u16) -> StdResult<Option<String>> {
    Ok(SUBNET_OWNER.may_load(store, netuid)?.map(|a| a.to_string()))
}

pub fn get_hotkey_owner(store: &dyn Storage, hotkey: &Addr) -> StdResult<Option<String>> {
    Ok(OWNER.may_load(store, hotkey)?.map(|a| a.to_string()))
}

pub fn query_stake_for_coldkey_and_hotkey(
    store: &dyn Storage,
    hotkey: &Addr,
    coldkey: &Addr,
) -> StdResult<Option<u64>> {
    STAKE.may_load(store, (hotkey, coldkey))
}

pub fn query_uid_for_hotkey_on_subnet(
    store: &dyn Storage,
    hotkey: &Addr,
    netuid: u16,
) -> StdResult<Option<u16>> {
    UIDS.may_load(store, (netuid, hotkey))
}

pub fn query_subnet_exist(store: &dyn Storage, netuid: u16) -> StdResult<bool> {
    Ok(NETWORKS_ADDED.may_load(store, netuid)?.unwrap_or(false))
}

pub fn query_max_weight_limit(store: &dyn Storage, netuid: u16) -> StdResult<Option<u16>> {
    MAX_WEIGHTS_LIMIT.may_load(store, netuid)
}

pub fn query_min_allowed_weights(store: &dyn Storage, netuid: u16) -> StdResult<Option<u16>> {
    MIN_ALLOWED_WEIGHTS.may_load(store, netuid)
}

pub fn query_delegate_take(store: &dyn Storage, hotkey: &Addr) -> StdResult<Option<u16>> {
    DELEGATES.may_load(store, hotkey)
}

pub fn query_burn(store: &dyn Storage, netuid: u16) -> StdResult<Option<u64>> {
    BURN.may_load(store, netuid)
}

pub fn query_difficulty(store: &dyn Storage, netuid: u16) -> StdResult<Option<u64>> {
    DIFFICULTY.may_load(store, netuid)
}

pub fn query_tempo(store: &dyn Storage, netuid: u16) -> StdResult<Option<u16>> {
    TEMPO.may_load(store, netuid)
}

pub fn query_total_networks(store: &dyn Storage) -> StdResult<u16> {
    let total_networks = TOTAL_NETWORKS.load(store)?;
    Ok(total_networks)
}

pub fn query_networks_added(store: &dyn Storage) -> StdResult<Vec<u16>> {
    NETWORKS_ADDED
        .range(store, None, None, Order::Ascending)
        .map(|item| item.map(|(k, _)| k))
        .collect()
}

pub fn query_emission_value_by_subnet(deps: Deps, netuid: u16) -> StdResult<u64> {
    let emission_value = EMISSION_VALUES.load(deps.storage, netuid)?;
    Ok(emission_value)
}

pub fn query_all_subnet_netuids(store: &dyn Storage) -> StdResult<Vec<u16>> {
    NETWORKS_ADDED
        .range(store, None, None, Order::Ascending)
        .map(|item| item.map(|(k, _)| k))
        .collect()
}

pub fn query_netuids_for_hotkey(store: &dyn Storage, hotkey: &Addr) -> StdResult<Vec<u16>> {
    let networks = get_registered_networks_for_hotkey(store, hotkey);

    Ok(networks)
}

pub fn query_total_issuance(store: &dyn Storage) -> StdResult<u64> {
    let issuance = TOTAL_ISSUANCE.load(store)?;
    Ok(issuance)
}

pub fn query_total_stake(store: &dyn Storage) -> StdResult<u64> {
    let stake = TOTAL_STAKE.load(store)?;
    Ok(stake)
}

pub fn query_tx_rate_limit(store: &dyn Storage) -> StdResult<u64> {
    let limit = TX_RATE_LIMIT.load(store)?;
    Ok(limit)
}

pub fn query_get_axon_info(
    store: &dyn Storage,
    netuid: u16,
    hotkey: &Addr,
) -> StdResult<Option<AxonInfo>> {
    AXONS.may_load(store, (netuid, hotkey))
}

pub fn query_get_prometheus_info(
    store: &dyn Storage,
    netuid: u16,
    hotkey: &Addr,
) -> StdResult<Option<PrometheusInfo>> {
    PROMETHEUS.may_load(store, (netuid, hotkey))
}

pub fn query_get_total_stake_for_hotkey(
    store: &dyn Storage,
    hotkey: &Addr,
) -> StdResult<Option<u64>> {
    TOTAL_HOTKEY_STAKE.may_load(store, hotkey)
}

pub fn query_get_total_stake_for_coldkey(
    store: &dyn Storage,
    coldkey: &Addr,
) -> StdResult<Option<u64>> {
    TOTAL_COLDKEY_STAKE.may_load(store, coldkey)
}

pub fn query_get_hotkey_exist(store: &dyn Storage, hotkey: &Addr) -> StdResult<bool> {
    Ok(OWNER.may_load(store, hotkey)?.is_some())
}

pub fn query_get_stake(store: &dyn Storage, hotkey: &Addr) -> StdResult<Vec<(String, u64)>> {
    STAKE
        .prefix(hotkey)
        .range(store, None, None, Order::Ascending)
        .map(|item| item.map(|(address, stake)| (address.to_string(), stake)))
        .collect()
}

pub fn get_block_rewards(store: &dyn Storage) -> StdResult<Coin> {
    let block_rewards = BLOCK_EMISSION.load(store)?;
    let denom = DENOM.load(store)?;
    Ok(Coin::new(u128::from(block_rewards), denom))
}

pub fn get_subnet_metadata(store: &dyn Storage, netuid: u16) -> StdResult<Metadata> {
    let subnet_meta = NETWORKS_METADATA.load(store, netuid)?;
    Ok(subnet_meta)
}

pub fn get_subnets_metadata(
    store: &dyn Storage,
    start_after: Option<u16>,
    limit: Option<u16>,
) -> StdResult<Vec<(u16, Metadata)>> {
    let start = start_after.map(Bound::exclusive);
    let subnets_limit = limit.unwrap_or(32) as usize;

    NETWORKS_METADATA
        .range(store, start, None, Order::Ascending)
        .take(subnets_limit)
        .collect()
}

pub fn get_verse_metadata(store: &dyn Storage) -> StdResult<Metadata> {
    let verse_meta = VERSE_METADATA.load(store)?;
    Ok(verse_meta)
}

pub fn get_economy(store: &dyn Storage) -> StdResult<EconomyData> {
    let block_rewards = BLOCK_EMISSION.load(store)?;
    let denom = DENOM.load(store)?;
    let total_stake = TOTAL_STAKE.load(store)?;
    let default_take = DEFAULT_TAKE.load(store)?;
    let default_commission = Decimal::from_ratio(default_take, u16::MAX)
        .mul(Decimal::from_atomics(Uint128::from(100u64), 0).unwrap());
    let commission_change = COMMISSION_CHANGE.load(store)?;
    let blocks_per_year = 5256000u64;
    let total_issuance = TOTAL_ISSUANCE.load(store)?;
    let total_rewards = TOTAL_REWARDS.load(store)?;

    let (validator_apr, staker_apr) = if total_stake == 0 {
        (Decimal::zero(), Decimal::zero())
    } else {
        let yearly_emission =
            Decimal::new(Uint128::from(block_rewards).mul(Uint128::from(blocks_per_year)));
        let total_stake_dec = Decimal::new(Uint128::from(total_stake));
        let hundred = Decimal::from_atomics(Uint128::from(100u64), 0).unwrap();

        let v_apr = yearly_emission.div(total_stake_dec).mul(hundred);
        let s_apr = yearly_emission
            .div(total_stake_dec)
            .mul(Decimal::one().sub(Decimal::from_ratio(default_take, u16::MAX)))
            .mul(hundred);
        (v_apr, s_apr)
    };

    let total_rewards = Coin::new(u128::from(total_rewards), denom.clone());

    let economy_data = EconomyData {
        validator_apr,
        staker_apr,
        block_rewards: Coin::new(u128::from(block_rewards), denom.clone()),
        total_stake: Coin::new(u128::from(total_stake), denom.clone()),
        default_commission,
        commission_change,
        total_issuance: Coin::new(u128::from(total_issuance), denom),
        total_rewards,
    };

    Ok(economy_data)
}

#[cfg_attr(not(feature = "library"), entry_point)]
pub fn migrate(deps: DepsMut, _env: Env, _msg: MigrateMsg) -> Result<Response, ContractError> {
    let storage_version: ContractVersion = get_contract_version(deps.storage)?;

    // Only migrate if newer (semantic version comparison)
    let stored = storage_version
        .version
        .parse::<semver::Version>()
        .map_err(|_| ContractError::MigrationError {})?;
    let current = CONTRACT_VERSION
        .parse::<semver::Version>()
        .map_err(|_| ContractError::MigrationError {})?;
    if stored < current {
        // Set contract to version to latest
        set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;
    } else {
        return Err(ContractError::MigrationError {});
    }

    Ok(Response::new().add_attribute("action", "migrate"))
}

Dimensions

cw-cyber/contracts/hub-networks/src/contract.rs
cw-cyber/contracts/std-test/src/contract.rs
cw-cyber/contracts/hub-skills/src/contract.rs
cw-cyber/contracts/litium-refer/src/contract.rs
cw-cyber/contracts/hub-libs/src/contract.rs
cw-cyber/contracts/litium-mine/src/contract.rs
cw-cyber/contracts/litium-wrap/src/contract.rs
cw-cyber/contracts/litium-stake/src/contract.rs
cw-cyber/contracts/hub-protocols/src/contract.rs
cw-cyber/contracts/cw-cyber-passport/src/contract.rs
cw-cyber/contracts/graph-filter/src/contract.rs
cw-cyber/contracts/cw-cyber-subgraph/src/contract.rs
cw-cyber/contracts/litium-core/src/contract.rs
cw-cyber/contracts/hub-channels/src/contract.rs
cw-cyber/contracts/cw-cyber-gift/src/contract.rs
cw-cyber/contracts/hub-tokens/src/contract.rs

Local Graph