use {
solana_instruction::Instruction, solana_program_error::ProgramError, solana_pubkey::Pubkey,
spl_token_2022_interface::error::TokenError,
};
pub mod instruction;
pub mod processor;
#[deprecated(
since = "9.1.0",
note = "Use spl_token_2022_interface instead and remove spl_token_2022 as a dependency"
)]
pub use spl_token_2022_interface::extension::memo_transfer::{memo_required, MemoTransfer};
pub fn check_previous_sibling_instruction_is_memo() -> Result<(), ProgramError> {
let is_memo_program = |program_id: &Pubkey| -> bool {
program_id == &spl_memo_interface::v3::id() || program_id == &spl_memo_interface::v1::id()
};
let previous_instruction = get_processed_sibling_instruction();
match previous_instruction {
Some(instruction) if is_memo_program(&instruction.program_id) => {}
_ => {
return Err(TokenError::NoMemo.into());
}
}
Ok(())
}
fn get_processed_sibling_instruction() -> Option<Instruction> {
#[cfg(target_os = "solana")]
#[allow(unsafe_code)]
{
use solana_instruction::{syscalls, AccountMeta, ProcessedSiblingInstruction};
let mut meta = ProcessedSiblingInstruction::default();
let mut program_id = Pubkey::default();
if 1 == unsafe {
syscalls::sol_get_processed_sibling_instruction(
0,
&mut meta,
&mut program_id,
&mut u8::default(),
&mut AccountMeta::default(),
)
} {
let mut data = Vec::new();
let mut accounts = Vec::new();
data.resize_with(meta.data_len as usize, u8::default);
accounts.resize_with(meta.accounts_len as usize, AccountMeta::default);
let _ = unsafe {
syscalls::sol_get_processed_sibling_instruction(
0,
&mut meta,
&mut program_id,
data.as_mut_ptr(),
accounts.as_mut_ptr(),
)
};
Some(Instruction::new_with_bytes(program_id, &data, accounts))
} else {
None
}
}
#[cfg(not(target_os = "solana"))]
{
None
}
}