#[cfg(feature = "serde-traits")]
use serde::{Deserialize, Serialize};
use {
crate::{
extension::{
BaseState, BaseStateWithExtensions, Extension, ExtensionType, StateWithExtensionsMut,
},
state::Account,
},
bytemuck::{Pod, Zeroable},
solana_program::{account_info::AccountInfo, program_error::ProgramError, pubkey::Pubkey},
spl_pod::{optional_keys::OptionalNonZeroPubkey, primitives::PodBool},
};
pub mod instruction;
pub mod processor;
#[repr(C)]
#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde-traits", serde(rename_all = "camelCase"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
pub struct TransferHook {
pub authority: OptionalNonZeroPubkey,
pub program_id: OptionalNonZeroPubkey,
}
#[cfg_attr(feature = "serde-traits", derive(Serialize, Deserialize))]
#[cfg_attr(feature = "serde-traits", serde(rename_all = "camelCase"))]
#[derive(Clone, Copy, Debug, Default, PartialEq, Pod, Zeroable)]
#[repr(transparent)]
pub struct TransferHookAccount {
pub transferring: PodBool,
}
impl Extension for TransferHook {
const TYPE: ExtensionType = ExtensionType::TransferHook;
}
impl Extension for TransferHookAccount {
const TYPE: ExtensionType = ExtensionType::TransferHookAccount;
}
pub fn get_program_id<S: BaseState, BSE: BaseStateWithExtensions<S>>(
state: &BSE,
) -> Option<Pubkey> {
state
.get_extension::<TransferHook>()
.ok()
.and_then(|e| Option::<Pubkey>::from(e.program_id))
}
pub fn set_transferring(account: &mut StateWithExtensionsMut<Account>) -> Result<(), ProgramError> {
let account_extension = account.get_extension_mut::<TransferHookAccount>()?;
account_extension.transferring = true.into();
Ok(())
}
pub fn unset_transferring(account_info: &AccountInfo) -> Result<(), ProgramError> {
let mut account_data = account_info.data.borrow_mut();
let mut account = StateWithExtensionsMut::<Account>::unpack(&mut account_data)?;
let account_extension = account.get_extension_mut::<TransferHookAccount>()?;
account_extension.transferring = false.into();
Ok(())
}