use crate::{
account_set::{
modifiers::{CanInitSeeds, SignedAccount},
single_set::SingleSetMeta,
AccountSetValidate,
},
prelude::*,
};
use derive_more::{Deref, DerefMut};
#[derive(AccountSet, Copy, Clone, Debug, Deref, DerefMut)]
#[repr(transparent)]
#[account_set(skip_default_idl)]
#[validate(
extra_validation = if SIGNER { self.check_signer() } else { Ok(()) }
)]
pub struct MaybeSigner<const SIGNER: bool, T>(
#[single_account_set(meta = SingleSetMeta { signer: SIGNER, ..T::meta() }, skip_signed_account, skip_can_init_seeds)]
pub(crate) T,
);
pub type Signer<T = AccountInfo> = MaybeSigner<true, T>;
impl<T> SignedAccount for MaybeSigner<true, T>
where
T: SingleAccountSet,
{
#[inline]
fn signer_seeds(&self) -> Option<Vec<&[u8]>> {
None
}
}
impl<T> SignedAccount for MaybeSigner<false, T>
where
T: SignedAccount,
{
#[inline]
fn signer_seeds(&self) -> Option<Vec<&[u8]>> {
self.0.signer_seeds()
}
}
impl<T, A> CanInitSeeds<A> for MaybeSigner<true, T>
where
Self: SingleAccountSet + AccountSetValidate<A>,
{
#[inline]
fn init_seeds(&mut self, _arg: &A, _ctx: &Context) -> Result<()> {
Ok(())
}
}
impl<T, A> CanInitSeeds<A> for MaybeSigner<false, T>
where
T: CanInitSeeds<A>,
{
#[inline]
fn init_seeds(&mut self, arg: &A, ctx: &Context) -> Result<()> {
self.0.init_seeds(arg, ctx)
}
}
#[cfg(all(feature = "idl", not(target_os = "solana")))]
mod idl_impl {
use super::*;
use star_frame::idl::AccountSetToIdl;
use star_frame_idl::{account_set::IdlAccountSetDef, IdlDefinition};
impl<const SIGNER: bool, T, A> AccountSetToIdl<A> for MaybeSigner<SIGNER, T>
where
T: AccountSetToIdl<A>,
{
fn account_set_to_idl(
idl_definition: &mut IdlDefinition,
arg: A,
) -> crate::IdlResult<IdlAccountSetDef> {
let mut set = T::account_set_to_idl(idl_definition, arg)?;
if SIGNER {
set.single()?.signer = true;
}
Ok(set)
}
}
}