use solana_sdk::pubkey::Pubkey;
use solana_system_interface::program as system_program;
use spl_token::solana_program::program_pack::Pack;
use spl_token::state::Account as SplTokenStateAccount;
#[inline]
pub fn read_pubkey(data: &[u8], offset: usize) -> Option<Pubkey> {
if data.len() < offset + 32 {
return None;
}
let bytes: [u8; 32] = data[offset..offset + 32].try_into().ok()?;
Some(Pubkey::new_from_array(bytes))
}
#[inline]
pub fn read_u64_le(data: &[u8], offset: usize) -> Option<u64> {
if data.len() < offset + 8 {
return None;
}
Some(u64::from_le_bytes(data[offset..offset + 8].try_into().ok()?))
}
#[inline]
pub fn read_u16_le(data: &[u8], offset: usize) -> Option<u16> {
if data.len() < offset + 2 {
return None;
}
Some(u16::from_le_bytes(data[offset..offset + 2].try_into().ok()?))
}
#[inline]
pub fn read_u8(data: &[u8], offset: usize) -> Option<u8> {
data.get(offset).copied()
}
#[inline]
pub fn is_nonce_account(data: &[u8]) -> bool {
data.len() >= 8 && &data[0..8] == &[1, 0, 0, 0, 1, 0, 0, 0]
}
#[inline]
pub fn is_token_program_account(owner: &Pubkey) -> bool {
owner.to_bytes() == spl_token::ID.to_bytes()
|| owner.to_bytes() == spl_token_2022::ID.to_bytes()
}
#[inline]
pub fn user_wallet_pubkey_for_onchain_account(
address: &Pubkey,
owner: &Pubkey,
data: &[u8],
executable: bool,
) -> Option<Pubkey> {
if executable {
return None;
}
if owner == &system_program::id() {
return if data.is_empty() { Some(*address) } else { None };
}
if is_token_program_account(owner) && data.len() == SplTokenStateAccount::LEN {
let ta = SplTokenStateAccount::unpack(data).ok()?;
return Some(Pubkey::new_from_array(ta.owner.to_bytes()));
}
None
}
#[inline]
pub fn has_discriminator(data: &[u8], discriminator: &[u8]) -> bool {
if data.len() < discriminator.len() {
return false;
}
&data[0..discriminator.len()] == discriminator
}