use crate::prelude::*;
use std::collections::HashMap;
use cw_storage_plus::{Key, KeyDeserialize, PrimaryKey};
use once_cell::sync::Lazy;
#[derive(Debug, Clone, Copy)]
pub enum ShutdownWallet {
KillSwitch,
WindDown,
}
#[cw_serde]
#[derive(enum_iterator::Sequence, Copy, Hash, Eq, PartialOrd, Ord)]
pub enum ShutdownImpact {
NewTrades,
ClosePositions,
OwnerActions,
DepositLiquidity,
WithdrawLiquidity,
Staking,
Unstaking,
TransferPositions,
TransferLp,
SetPrice,
TransferDaoFees,
Crank,
SetManualPrice,
}
impl ShutdownImpact {
pub fn can_perform(self, shutdown_wallet: ShutdownWallet) -> bool {
match (shutdown_wallet, self) {
(ShutdownWallet::KillSwitch, _) => true,
(ShutdownWallet::WindDown, ShutdownImpact::NewTrades) => true,
(ShutdownWallet::WindDown, ShutdownImpact::ClosePositions) => false,
(ShutdownWallet::WindDown, ShutdownImpact::OwnerActions) => false,
(ShutdownWallet::WindDown, ShutdownImpact::DepositLiquidity) => true,
(ShutdownWallet::WindDown, ShutdownImpact::WithdrawLiquidity) => false,
(ShutdownWallet::WindDown, ShutdownImpact::Staking) => true,
(ShutdownWallet::WindDown, ShutdownImpact::Unstaking) => false,
(ShutdownWallet::WindDown, ShutdownImpact::TransferPositions) => false,
(ShutdownWallet::WindDown, ShutdownImpact::TransferLp) => false,
(ShutdownWallet::WindDown, ShutdownImpact::SetPrice) => false,
(ShutdownWallet::WindDown, ShutdownImpact::TransferDaoFees) => false,
(ShutdownWallet::WindDown, ShutdownImpact::Crank) => false,
(ShutdownWallet::WindDown, ShutdownImpact::SetManualPrice) => false,
}
}
pub fn ensure_can_perform(self, shutdown_wallet: ShutdownWallet) -> Result<()> {
if self.can_perform(shutdown_wallet) {
Ok(())
} else {
let msg = format!("{shutdown_wallet:?} cannot perform {self:?}");
Err(anyhow!(PerpError::auth(ErrorDomain::Factory, msg)))
}
}
pub fn for_market_execute_msg(
msg: &crate::contracts::market::entry::ExecuteMsg,
) -> Option<Self> {
use crate::contracts::market::entry::ExecuteMsg;
match msg {
ExecuteMsg::Owner(_) => Some(Self::OwnerActions),
ExecuteMsg::Receive { .. } => None,
ExecuteMsg::OpenPosition { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionAddCollateralImpactLeverage { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionAddCollateralImpactSize { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionRemoveCollateralImpactLeverage { .. } => {
Some(Self::NewTrades)
}
ExecuteMsg::UpdatePositionRemoveCollateralImpactSize { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionLeverage { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionMaxGains { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionTakeProfitPrice { .. } => Some(Self::NewTrades),
ExecuteMsg::UpdatePositionStopLossPrice { .. } => Some(Self::NewTrades),
#[allow(deprecated)]
ExecuteMsg::SetTriggerOrder { .. } => Some(Self::NewTrades),
ExecuteMsg::ClosePosition { .. } => Some(Self::ClosePositions),
ExecuteMsg::DepositLiquidity { .. } => Some(Self::DepositLiquidity),
ExecuteMsg::ReinvestYield { .. } => Some(Self::DepositLiquidity),
ExecuteMsg::WithdrawLiquidity { .. } => Some(Self::WithdrawLiquidity),
ExecuteMsg::ClaimYield {} => Some(Self::WithdrawLiquidity),
ExecuteMsg::StakeLp { .. } => Some(Self::Staking),
ExecuteMsg::UnstakeXlp { .. } => Some(Self::Unstaking),
ExecuteMsg::StopUnstakingXlp {} => Some(Self::Unstaking),
ExecuteMsg::CollectUnstakedLp {} => Some(Self::Unstaking),
ExecuteMsg::Crank { .. } => Some(Self::Crank),
ExecuteMsg::NftProxy { .. } => Some(Self::TransferPositions),
ExecuteMsg::LiquidityTokenProxy { .. } => Some(Self::TransferLp),
ExecuteMsg::TransferDaoFees { .. } => Some(Self::TransferDaoFees),
ExecuteMsg::CloseAllPositions {} => None,
ExecuteMsg::PlaceLimitOrder { .. } => Some(Self::NewTrades),
ExecuteMsg::CancelLimitOrder { .. } => Some(Self::ClosePositions),
ExecuteMsg::ProvideCrankFunds {} => Some(Self::Crank),
ExecuteMsg::SetManualPrice { .. } => Some(Self::SetManualPrice),
ExecuteMsg::PerformDeferredExec { .. } => None,
}
}
}
#[cw_serde]
#[derive(Copy)]
pub enum ShutdownEffect {
Disable,
Enable,
}
impl ShutdownImpact {
pub(crate) fn as_bytes(self) -> &'static [u8] {
static LOOKUP: Lazy<HashMap<ShutdownImpact, Vec<u8>>> = Lazy::new(|| {
enum_iterator::all::<ShutdownImpact>()
.map(|x| (x, format!("{x:?}").into_bytes()))
.collect()
});
LOOKUP
.get(&self)
.expect("Impossible! ShutdownImpact::as_bytes failed")
}
pub(crate) fn try_from_bytes(bytes: &[u8]) -> Result<Self> {
static LOOKUP: Lazy<HashMap<Vec<u8>, ShutdownImpact>> = Lazy::new(|| {
enum_iterator::all::<ShutdownImpact>()
.map(|x| (format!("{x:?}").into_bytes(), x))
.collect()
});
LOOKUP.get(bytes).copied().with_context(|| {
format!(
"Unable to parse as ShutdownImpact: {:?}",
std::str::from_utf8(bytes)
)
})
}
}
impl KeyDeserialize for ShutdownImpact {
type Output = ShutdownImpact;
const KEY_ELEMS: u16 = 1;
fn from_vec(value: Vec<u8>) -> cosmwasm_std::StdResult<Self::Output> {
ShutdownImpact::try_from_bytes(&value)
.map_err(|x| cosmwasm_std::StdError::parse_err("ShutdownImpact", x))
}
}
impl<'a> PrimaryKey<'a> for ShutdownImpact {
type Prefix = ();
type SubPrefix = ();
type Suffix = Self;
type SuperSuffix = Self;
fn key(&self) -> Vec<Key> {
vec![Key::Ref(self.as_bytes())]
}
}