use serde::{Deserialize, Serialize};
use solana_program::program_error::ProgramError;
use solana_program::log::sol_log;
use steel::*;
use crate::consts::WHITELIST;
use super::OilAccount;
#[repr(C)]
#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable, Serialize, Deserialize)]
pub struct Whitelist {
pub code_hash: [u8; 32],
pub usage_count: u64,
}
impl Whitelist {
pub fn pda(code_hash: [u8; 32]) -> (Pubkey, u8) {
use crate::ID;
Pubkey::find_program_address(&[WHITELIST, &code_hash], &ID)
}
pub fn validate_premine_code<'a>(
is_premine: bool,
has_access_code: bool,
access_code_hash: [u8; 32],
whitelist_info_opt: Option<&AccountInfo<'a>>,
) -> Result<(), ProgramError> {
if is_premine {
if !has_access_code {
return Err(ProgramError::InvalidArgument); }
let whitelist_info = whitelist_info_opt.ok_or(ProgramError::NotEnoughAccountKeys)?;
let (whitelist_pda, _) = Self::pda(access_code_hash);
whitelist_info.has_address(&whitelist_pda)?;
if whitelist_info.data_is_empty() {
return Err(ProgramError::InvalidArgument); }
let whitelist = whitelist_info.as_account::<Whitelist>(&crate::ID)?;
if whitelist.code_hash != access_code_hash {
return Err(ProgramError::InvalidArgument); }
let whitelist_mut = whitelist_info.as_account_mut::<Whitelist>(&crate::ID)?;
whitelist_mut.usage_count = whitelist_mut.usage_count.saturating_add(1);
sol_log(&format!(
"Pre-mine: access code validated, usage_count={}",
whitelist_mut.usage_count
));
} else if has_access_code {
sol_log("Access code provided but pre-mine is not active - ignoring");
}
Ok(())
}
}
account!(OilAccount, Whitelist);