code/pallets/subtensor/src/rpc_info/gamma_info.rs

gamma_info.rs

91 lines · 3,455 bytes · 8b2a978a98RawGitHub
//! Gamma reads for `GammaRuntimeApi`.

use frame_support::pallet_prelude::{Decode, Encode};
use frame_support::storage::{TransactionOutcome, with_transaction};
use subtensor_runtime_common::{AlphaBalance, GammaBalance, NetUid, TaoBalance};
use subtensor_swap_interface::SwapHandler;

use super::*;

/// A gamma deposit and what its spender can spend from it now.
#[freeze_struct("1fbec154e8c48c46")]
#[derive(Decode, Encode, PartialEq, Eq, Clone, Debug, TypeInfo)]
pub struct GammaDepositInfo<AccountId: TypeInfo + Encode + Decode> {
    pub netuid: NetUid,
    pub hotkey: AccountId,
    pub deposit: GammaDeposit<AccountId>,
    /// The deposit's balance within what its daily spend cap allows now.
    pub spendable: GammaBalance,
}

impl<T: Config> Pallet<T> {
    fn gamma_deposit_info(
        netuid: NetUid,
        hotkey: T::AccountId,
        deposit: GammaDeposit<T::AccountId>,
    ) -> GammaDepositInfo<T::AccountId> {
        let spendable = Self::gamma_allowance(&deposit, Self::get_current_block_as_u64())
            .map_or(deposit.balance, |allowance| allowance.min(deposit.balance));
        GammaDepositInfo {
            netuid,
            hotkey,
            deposit,
            spendable,
        }
    }

    /// The deposit at `hotkey` on `netuid`.
    pub fn get_gamma_deposit(
        netuid: NetUid,
        hotkey: T::AccountId,
    ) -> Option<GammaDepositInfo<T::AccountId>> {
        let deposit = GammaDeposits::<T>::get(netuid, &hotkey)?;
        Some(Self::gamma_deposit_info(netuid, hotkey, deposit))
    }

    /// Every deposit `coldkey` owns, on every subnet.
    pub fn get_gamma_deposits_for_coldkey(
        coldkey: &T::AccountId,
    ) -> Vec<GammaDepositInfo<T::AccountId>> {
        Self::get_all_subnet_netuids()
            .into_iter()
            .flat_map(|netuid| {
                ColdkeyGammaHotkeys::<T>::get(netuid, coldkey)
                    .into_iter()
                    .filter_map(move |hotkey| Self::get_gamma_deposit(netuid, hotkey))
            })
            .collect()
    }

    /// The alpha burned, TAO value and gamma `mint_gamma` would mint for `amount` now, or the
    /// error that stops it.
    pub fn sim_mint_gamma(
        netuid: NetUid,
        amount: TaoBalance,
    ) -> Result<(AlphaBalance, TaoBalance, GammaBalance), DispatchError> {
        with_transaction(|| {
            TransactionOutcome::Rollback((|| {
                Self::ensure_gamma_mintable(netuid)?;
                Self::ensure_add_stake_input_within_swap_limit(netuid, amount)?;
                let mark = Self::gamma_mark(netuid);
                let swap =
                    Self::swap_tao_for_alpha(netuid, amount, T::SwapInterface::max_price(), false)?;
                let alpha = swap.amount_paid_out;
                let (value, gamma) = Self::gamma_for_alpha(alpha, mark)?;
                Ok::<_, DispatchError>((alpha, value, gamma))
            })())
        })
    }

    /// `alpha_amount` and the TAO value and gamma of burning it now, or the error that stops
    /// it; it reads no stake.
    pub fn sim_mint_gamma_with_stake(
        netuid: NetUid,
        alpha_amount: AlphaBalance,
    ) -> Result<(AlphaBalance, TaoBalance, GammaBalance), DispatchError> {
        Self::ensure_gamma_mintable(netuid)?;
        let mark = Self::gamma_mark(netuid);
        let (value, gamma) = Self::gamma_for_alpha(alpha_amount, mark)?;
        Ok((alpha_amount, value, gamma))
    }
}