// This file is autogenerated with https://github.com/acheroncrypto/native-to-anchor

use anchor_lang::prelude::*;

declare_id!("11111111111111111111111111111111");

#[program]
pub mod spl_stake_pool {
    use super::*;

    pub fn initialize(
        ctx: Context<Initialize>,
        fee: Fee,
        withdrawal_fee: Fee,
        deposit_fee: Fee,
        referral_fee: u8,
        max_validators: u32,
    ) -> Result<()> {
        Ok(())
    }

    pub fn add_validator_to_pool(ctx: Context<AddValidatorToPool>) -> Result<()> {
        Ok(())
    }

    pub fn remove_validator_from_pool(ctx: Context<RemoveValidatorFromPool>) -> Result<()> {
        Ok(())
    }

    pub fn decrease_validator_stake(
        ctx: Context<DecreaseValidatorStake>,
        lamports: u64,
        transient_stake_seed: u64,
    ) -> Result<()> {
        Ok(())
    }

    pub fn increase_validator_stake(
        ctx: Context<IncreaseValidatorStake>,
        lamports: u64,
        transient_stake_seed: u64,
    ) -> Result<()> {
        Ok(())
    }

    pub fn set_preferred_validator(
        ctx: Context<SetPreferredValidator>,
        validator_type: PreferredValidatorType,
        validator_vote_address: Option<Pubkey>,
    ) -> Result<()> {
        Ok(())
    }

    pub fn update_validator_list_balance(
        ctx: Context<UpdateValidatorListBalance>,
        start_index: u32,
        no_merge: bool,
    ) -> Result<()> {
        Ok(())
    }

    pub fn update_stake_pool_balance(ctx: Context<UpdateStakePoolBalance>) -> Result<()> {
        Ok(())
    }

    pub fn cleanup_removed_validator_entries(
        ctx: Context<CleanupRemovedValidatorEntries>,
    ) -> Result<()> {
        Ok(())
    }

    pub fn deposit_stake(ctx: Context<DepositStake>) -> Result<()> {
        Ok(())
    }

    pub fn withdraw_stake(ctx: Context<WithdrawStake>, arg: u64) -> Result<()> {
        Ok(())
    }

    pub fn set_manager(ctx: Context<SetManager>) -> Result<()> {
        Ok(())
    }

    pub fn set_fee(ctx: Context<SetFee>, fee: FeeType) -> Result<()> {
        Ok(())
    }

    pub fn set_staker(ctx: Context<SetStaker>) -> Result<()> {
        Ok(())
    }

    pub fn deposit_sol(ctx: Context<DepositSol>, arg: u64) -> Result<()> {
        Ok(())
    }

    pub fn set_funding_authority(
        ctx: Context<SetFundingAuthority>,
        arg: FundingType,
    ) -> Result<()> {
        Ok(())
    }

    pub fn withdraw_sol(ctx: Context<WithdrawSol>, arg: u64) -> Result<()> {
        Ok(())
    }

    pub fn create_token_metadata(
        ctx: Context<CreateTokenMetadata>,
        name: String,
        symbol: String,
        uri: String,
    ) -> Result<()> {
        Ok(())
    }

    pub fn update_token_metadata(
        ctx: Context<UpdateTokenMetadata>,
        name: String,
        symbol: String,
        uri: String,
    ) -> Result<()> {
        Ok(())
    }
}

#[derive(Accounts)]
pub struct Initialize<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
    staker: AccountInfo<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list: AccountInfo<'info>,
    reserve_stake: AccountInfo<'info>,
    #[account(mut)]
    pool_mint: AccountInfo<'info>,
    #[account(mut)]
    manager_pool_account: AccountInfo<'info>,
    token_program: Program<'info, Token>,
    // optional_deposit_authority: Signer<'info>,
}

#[derive(Accounts)]
pub struct AddValidatorToPool<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    staker: Signer<'info>,
    #[account(mut)]
    funder: Signer<'info>,
    stake_pool_withdraw: AccountInfo<'info>,
    #[account(mut)]
    validator_list: AccountInfo<'info>,
    #[account(mut)]
    stake: AccountInfo<'info>,
    validator: AccountInfo<'info>,
    rent: Sysvar<'info, Rent>,
    clock: Sysvar<'info, Clock>,
    sysvar_stake_history: AccountInfo<'info>,
    stake_config: AccountInfo<'info>,
    system_program: Program<'info, System>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct RemoveValidatorFromPool<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    staker: Signer<'info>,
    stake_pool_withdraw: AccountInfo<'info>,
    new_stake_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list: AccountInfo<'info>,
    #[account(mut)]
    stake_account: AccountInfo<'info>,
    transient_stake_account: AccountInfo<'info>,
    #[account(mut)]
    destination_stake_account: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct DecreaseValidatorStake<'info> {
    stake_pool: AccountInfo<'info>,
    staker: Signer<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list: AccountInfo<'info>,
    #[account(mut)]
    validator_stake: AccountInfo<'info>,
    #[account(mut)]
    transient_stake: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    rent: Sysvar<'info, Rent>,
    system_program: Program<'info, System>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct IncreaseValidatorStake<'info> {
    stake_pool: AccountInfo<'info>,
    staker: Signer<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list: AccountInfo<'info>,
    #[account(mut)]
    reserve_stake: AccountInfo<'info>,
    #[account(mut)]
    transient_stake: AccountInfo<'info>,
    validator_stake: AccountInfo<'info>,
    validator: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    rent: Sysvar<'info, Rent>,
    sysvar_stake_history: AccountInfo<'info>,
    stake_config: AccountInfo<'info>,
    system_program: Program<'info, System>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct SetPreferredValidator<'info> {
    #[account(mut)]
    stake_pool_address: AccountInfo<'info>,
    staker: Signer<'info>,
    validator_list_address: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct UpdateValidatorListBalance<'info> {
    stake_pool: AccountInfo<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list_address: AccountInfo<'info>,
    #[account(mut)]
    reserve_stake: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    sysvar_stake_history: AccountInfo<'info>,
    stake_program: AccountInfo<'info>,
    // #[account(mut)]
    // optional_validator_stake_account: AccountInfo<'info>,
    // #[account(mut)]
    // optional_transient_stake_account: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct UpdateStakePoolBalance<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    validator_list_storage: AccountInfo<'info>,
    reserve_stake: AccountInfo<'info>,
    #[account(mut)]
    manager_fee_account: AccountInfo<'info>,
    #[account(mut)]
    stake_pool_mint: AccountInfo<'info>,
    token_program: Program<'info, Token>,
}

#[derive(Accounts)]
pub struct CleanupRemovedValidatorEntries<'info> {
    stake_pool: AccountInfo<'info>,
    #[account(mut)]
    validator_list_storage: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct DepositStake<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    #[account(mut)]
    validator_list_storage: AccountInfo<'info>,
    stake_pool_deposit_authority: AccountInfo<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    deposit_stake_address: AccountInfo<'info>,
    #[account(mut)]
    validator_stake_account: AccountInfo<'info>,
    #[account(mut)]
    reserve_stake_account: AccountInfo<'info>,
    #[account(mut)]
    pool_tokens_to: AccountInfo<'info>,
    #[account(mut)]
    manager_fee_account: AccountInfo<'info>,
    #[account(mut)]
    referrer_pool_tokens_account: AccountInfo<'info>,
    #[account(mut)]
    pool_mint: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    sysvar_stake_history: AccountInfo<'info>,
    token_program: Program<'info, Token>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct WithdrawStake<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    #[account(mut)]
    validator_list_storage: AccountInfo<'info>,
    stake_pool_withdraw: AccountInfo<'info>,
    #[account(mut)]
    stake_to_split: AccountInfo<'info>,
    #[account(mut)]
    stake_to_receive: AccountInfo<'info>,
    user_stake_authority: AccountInfo<'info>,
    user_transfer_authority: Signer<'info>,
    #[account(mut)]
    user_pool_token_account: AccountInfo<'info>,
    #[account(mut)]
    manager_fee_account: AccountInfo<'info>,
    #[account(mut)]
    pool_mint: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    token_program: Program<'info, Token>,
    stake_program: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct SetManager<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
    new_manager: Signer<'info>,
    new_fee_receiver: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct SetFee<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
}

#[derive(Accounts)]
pub struct SetStaker<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    set_staker_authority: Signer<'info>,
    new_staker: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct DepositSol<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    reserve_stake_account: AccountInfo<'info>,
    #[account(mut)]
    lamports_from: Signer<'info>,
    #[account(mut)]
    pool_tokens_to: AccountInfo<'info>,
    #[account(mut)]
    manager_fee_account: AccountInfo<'info>,
    #[account(mut)]
    referrer_pool_tokens_account: AccountInfo<'info>,
    #[account(mut)]
    pool_mint: AccountInfo<'info>,
    system_program: Program<'info, System>,
    token_program: Program<'info, Token>,
}

#[derive(Accounts)]
pub struct SetFundingAuthority<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
    // optional_auth: AccountInfo<'info>,
}

#[derive(Accounts)]
pub struct WithdrawSol<'info> {
    #[account(mut)]
    stake_pool: AccountInfo<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    user_transfer_authority: Signer<'info>,
    #[account(mut)]
    pool_tokens_from: AccountInfo<'info>,
    #[account(mut)]
    reserve_stake_account: AccountInfo<'info>,
    #[account(mut)]
    lamports_to: AccountInfo<'info>,
    #[account(mut)]
    manager_fee_account: AccountInfo<'info>,
    #[account(mut)]
    pool_mint: AccountInfo<'info>,
    clock: Sysvar<'info, Clock>,
    sysvar_stake_history: AccountInfo<'info>,
    stake_program: AccountInfo<'info>,
    token_program: Program<'info, Token>,
}

#[derive(Accounts)]
pub struct CreateTokenMetadata<'info> {
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    pool_mint: AccountInfo<'info>,
    #[account(mut)]
    payer: Signer<'info>,
    #[account(mut)]
    token_metadata: AccountInfo<'info>,
    mpl_token_metadata: AccountInfo<'info>,
    system_program: Program<'info, System>,
    rent: Sysvar<'info, Rent>,
}

#[derive(Accounts)]
pub struct UpdateTokenMetadata<'info> {
    stake_pool: AccountInfo<'info>,
    manager: Signer<'info>,
    stake_pool_withdraw_authority: AccountInfo<'info>,
    #[account(mut)]
    token_metadata: AccountInfo<'info>,
    mpl_token_metadata: AccountInfo<'info>,
}

#[account]
pub struct StakePool {
    /// Account type, must be StakePool currently
    pub account_type: AccountType,

    /// Manager authority, allows for updating the staker, manager, and fee account
    pub manager: Pubkey,

    /// Staker authority, allows for adding and removing validators, and managing stake
    /// distribution
    pub staker: Pubkey,

    /// Stake deposit authority
    ///
    /// If a depositor pubkey is specified on initialization, then deposits must be
    /// signed by this authority. If no deposit authority is specified,
    /// then the stake pool will default to the result of:
    /// `Pubkey::find_program_address(
    ///     &[&stake_pool_address.to_bytes()[..32], b"deposit"],
    ///     program_id,
    /// )`
    pub stake_deposit_authority: Pubkey,

    /// Stake withdrawal authority bump seed
    /// for `create_program_address(&[state::StakePool account, "withdrawal"])`
    pub stake_withdraw_bump_seed: u8,

    /// Validator stake list storage account
    pub validator_list: Pubkey,

    /// Reserve stake account, holds deactivated stake
    pub reserve_stake: Pubkey,

    /// Pool Mint
    pub pool_mint: Pubkey,

    /// Manager fee account
    pub manager_fee_account: Pubkey,

    /// Pool token program id
    pub token_program_id: Pubkey,

    /// Total stake under management.
    /// Note that if `last_update_epoch` does not match the current epoch then
    /// this field may not be accurate
    pub total_lamports: u64,

    /// Total supply of pool tokens (should always match the supply in the Pool Mint)
    pub pool_token_supply: u64,

    /// Last epoch the `total_lamports` field was updated
    pub last_update_epoch: u64,

    /// Lockup that all stakes in the pool must have
    pub lockup: Lockup,

    /// Fee taken as a proportion of rewards each epoch
    pub epoch_fee: Fee,

    /// Fee for next epoch
    pub next_epoch_fee: Option<Fee>,

    /// Preferred deposit validator vote account pubkey
    pub preferred_deposit_validator_vote_address: Option<Pubkey>,

    /// Preferred withdraw validator vote account pubkey
    pub preferred_withdraw_validator_vote_address: Option<Pubkey>,

    /// Fee assessed on stake deposits
    pub stake_deposit_fee: Fee,

    /// Fee assessed on withdrawals
    pub stake_withdrawal_fee: Fee,

    /// Future stake withdrawal fee, to be set for the following epoch
    pub next_stake_withdrawal_fee: Option<Fee>,

    /// Fees paid out to referrers on referred stake deposits.
    /// Expressed as a percentage (0 - 100) of deposit fees.
    /// i.e. `stake_deposit_fee`% of stake deposited is collected as deposit fees for every deposit
    /// and `stake_referral_fee`% of the collected stake deposit fees is paid out to the referrer
    pub stake_referral_fee: u8,

    /// Toggles whether the `DepositSol` instruction requires a signature from
    /// this `sol_deposit_authority`
    pub sol_deposit_authority: Option<Pubkey>,

    /// Fee assessed on SOL deposits
    pub sol_deposit_fee: Fee,

    /// Fees paid out to referrers on referred SOL deposits.
    /// Expressed as a percentage (0 - 100) of SOL deposit fees.
    /// i.e. `sol_deposit_fee`% of SOL deposited is collected as deposit fees for every deposit
    /// and `sol_referral_fee`% of the collected SOL deposit fees is paid out to the referrer
    pub sol_referral_fee: u8,

    /// Toggles whether the `WithdrawSol` instruction requires a signature from
    /// the `deposit_authority`
    pub sol_withdraw_authority: Option<Pubkey>,

    /// Fee assessed on SOL withdrawals
    pub sol_withdrawal_fee: Fee,

    /// Future SOL withdrawal fee, to be set for the following epoch
    pub next_sol_withdrawal_fee: Option<Fee>,

    /// Last epoch's total pool tokens, used only for APR estimation
    pub last_epoch_pool_token_supply: u64,

    /// Last epoch's total lamports, used only for APR estimation
    pub last_epoch_total_lamports: u64,
}

#[account]
pub struct ValidatorStakeInfo {
    /// Amount of active stake delegated to this validator, minus the minimum
    /// required stake amount of rent-exemption + `crate::MINIMUM_ACTIVE_STAKE`
    /// (currently 1 SOL).
    ///
    /// Note that if `last_update_epoch` does not match the current epoch then
    /// this field may not be accurate
    pub active_stake_lamports: u64,

    /// Amount of transient stake delegated to this validator
    ///
    /// Note that if `last_update_epoch` does not match the current epoch then
    /// this field may not be accurate
    pub transient_stake_lamports: u64,

    /// Last epoch the active and transient stake lamports fields were updated
    pub last_update_epoch: u64,

    /// Start of the validator transient account seed suffixess
    pub transient_seed_suffix_start: u64,

    /// End of the validator transient account seed suffixes
    pub transient_seed_suffix_end: u64,

    /// Status of the validator stake account
    pub status: StakeStatus,

    /// Validator vote account address
    pub vote_account_address: Pubkey,
}

#[account]
pub struct ValidatorList {
    /// Data outside of the validator list, separated out for cheaper deserializations
    pub header: ValidatorListHeader,

    /// List of stake info for each validator in the pool
    pub validators: Vec<ValidatorStakeInfo>,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum AccountType {
    /// If the account has not been initialized, the enum will be 0
    Uninitialized,
    /// Stake pool
    StakePool,
    /// Validator stake list
    ValidatorList,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct Fee {
    /// denominator of the fee ratio
    pub denominator: u64,
    /// numerator of the fee ratio
    pub numerator: u64,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub struct ValidatorListHeader {
    /// Account type, must be ValidatorList currently
    pub account_type: AccountType,

    /// Maximum allowable number of validators
    pub max_validators: u32,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum StakeStatus {
    /// Stake account is active, there may be a transient stake as well
    Active,
    /// Only transient stake account exists, when a transient stake is
    /// deactivating during validator removal
    DeactivatingTransient,
    /// No more validator stake accounts exist, entry ready for removal during
    /// `UpdateStakePoolBalance`
    ReadyForRemoval,
}

#[error_code]
pub enum StakePoolError {
    // 0.
    /// The account cannot be initialized because it is already being used.
    #[msg("AlreadyInUse")]
    AlreadyInUse,
    /// The program address provided doesn't match the value generated by the program.
    #[msg("InvalidProgramAddress")]
    InvalidProgramAddress,
    /// The stake pool state is invalid.
    #[msg("InvalidState")]
    InvalidState,
    /// The calculation failed.
    #[msg("CalculationFailure")]
    CalculationFailure,
    /// Stake pool fee > 1.
    #[msg("FeeTooHigh")]
    FeeTooHigh,

    // 5.
    /// Token account is associated with the wrong mint.
    #[msg("WrongAccountMint")]
    WrongAccountMint,
    /// Wrong pool manager account.
    #[msg("WrongManager")]
    WrongManager,
    /// Required signature is missing.
    #[msg("SignatureMissing")]
    SignatureMissing,
    /// Invalid validator stake list account.
    #[msg("InvalidValidatorStakeList")]
    InvalidValidatorStakeList,
    /// Invalid manager fee account.
    #[msg("InvalidFeeAccount")]
    InvalidFeeAccount,

    // 10.
    /// Specified pool mint account is wrong.
    #[msg("WrongPoolMint")]
    WrongPoolMint,
    /// Stake account is not in the state expected by the program.
    #[msg("WrongStakeState")]
    WrongStakeState,
    /// User stake is not active
    #[msg("UserStakeNotActive")]
    UserStakeNotActive,
    /// Stake account voting for this validator already exists in the pool.
    #[msg("ValidatorAlreadyAdded")]
    ValidatorAlreadyAdded,
    /// Stake account for this validator not found in the pool.
    #[msg("ValidatorNotFound")]
    ValidatorNotFound,

    // 15.
    /// Stake account address not properly derived from the validator address.
    #[msg("InvalidStakeAccountAddress")]
    InvalidStakeAccountAddress,
    /// Identify validator stake accounts with old balances and update them.
    #[msg("StakeListOutOfDate")]
    StakeListOutOfDate,
    /// First update old validator stake account balances and then pool stake balance.
    #[msg("StakeListAndPoolOutOfDate")]
    StakeListAndPoolOutOfDate,
    /// Validator stake account is not found in the list storage.
    #[msg("UnknownValidatorStakeAccount")]
    UnknownValidatorStakeAccount,
    /// Wrong minting authority set for mint pool account
    #[msg("WrongMintingAuthority")]
    WrongMintingAuthority,

    // 20.
    /// The size of the given validator stake list does match the expected amount
    #[msg("UnexpectedValidatorListAccountSize")]
    UnexpectedValidatorListAccountSize,
    /// Wrong pool staker account.
    #[msg("WrongStaker")]
    WrongStaker,
    /// Pool token supply is not zero on initialization
    #[msg("NonZeroPoolTokenSupply")]
    NonZeroPoolTokenSupply,
    /// The lamports in the validator stake account is not equal to the minimum
    #[msg("StakeLamportsNotEqualToMinimum")]
    StakeLamportsNotEqualToMinimum,
    /// The provided deposit stake account is not delegated to the preferred deposit vote account
    #[msg("IncorrectDepositVoteAddress")]
    IncorrectDepositVoteAddress,

    // 25.
    /// The provided withdraw stake account is not the preferred deposit vote account
    #[msg("IncorrectWithdrawVoteAddress")]
    IncorrectWithdrawVoteAddress,
    /// The mint has an invalid freeze authority
    #[msg("InvalidMintFreezeAuthority")]
    InvalidMintFreezeAuthority,
    /// Proposed fee increase exceeds stipulated ratio
    #[msg("FeeIncreaseTooHigh")]
    FeeIncreaseTooHigh,
    /// Not enough pool tokens provided to withdraw stake with one lamport
    #[msg("WithdrawalTooSmall")]
    WithdrawalTooSmall,
    /// Not enough lamports provided for deposit to result in one pool token
    #[msg("DepositTooSmall")]
    DepositTooSmall,

    // 30.
    /// Provided stake deposit authority does not match the program's
    #[msg("InvalidStakeDepositAuthority")]
    InvalidStakeDepositAuthority,
    /// Provided sol deposit authority does not match the program's
    #[msg("InvalidSolDepositAuthority")]
    InvalidSolDepositAuthority,
    /// Provided preferred validator is invalid
    #[msg("InvalidPreferredValidator")]
    InvalidPreferredValidator,
    /// Provided validator stake account already has a transient stake account in use
    #[msg("TransientAccountInUse")]
    TransientAccountInUse,
    /// Provided sol withdraw authority does not match the program's
    #[msg("InvalidSolWithdrawAuthority")]
    InvalidSolWithdrawAuthority,

    // 35.
    /// Too much SOL withdrawn from the stake pool's reserve account
    #[msg("SolWithdrawalTooLarge")]
    SolWithdrawalTooLarge,
    /// Provided metadata account does not match metadata account derived for pool mint
    #[msg("InvalidMetadataAccount")]
    InvalidMetadataAccount,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum PreferredValidatorType {
    /// Set preferred validator for deposits
    Deposit,
    /// Set preferred validator for withdraws
    Withdraw,
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum FeeType {
    /// Referral fees for SOL deposits
    SolReferral(u8),
    /// Referral fees for stake deposits
    StakeReferral(u8),
    /// Management fee paid per epoch
    Epoch(Fee),
    /// Stake withdrawal fee
    StakeWithdrawal(Fee),
    /// Deposit fee for SOL deposits
    SolDeposit(Fee),
    /// Deposit fee for stake deposits
    StakeDeposit(Fee),
    /// SOL withdrawal fee
    SolWithdrawal(Fee),
}

#[derive(AnchorSerialize, AnchorDeserialize)]
pub enum FundingType {
    /// Sets the stake deposit authority
    StakeDeposit,
    /// Sets the SOL deposit authority
    SolDeposit,
    /// Sets the SOL withdraw authority
    SolWithdraw,
}
