use borsh::BorshSerialize;
use solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
msg,
program::invoke,
program_error::ProgramError,
program_pack::Pack,
pubkey::Pubkey,
};
use crate::{
instruction::YesNoInstruction,
state::{Bet, YesNoQuestion},
};
pub struct Processor {}
impl Processor {
pub fn process(program_id: &Pubkey, accounts: &[AccountInfo], input: &[u8]) -> ProgramResult {
let i = YesNoInstruction::unpack(input)?;
match i {
YesNoInstruction::CreateQuestion { name, deadline } => {
msg!("process create question");
return Self::process_create_question(program_id, accounts, name, deadline);
}
YesNoInstruction::Bet { yesno } => {
msg!("process create question");
return Self::process_bet(program_id, accounts, yesno);
}
YesNoInstruction::CloseQuestion => {
msg!("process close question");
return Self::process_close_question(program_id, accounts);
}
}
}
pub fn process_create_question(
program_id: &Pubkey,
accounts: &[AccountInfo],
title: &str,
deadline: u64,
) -> ProgramResult {
let accs_iter = &mut accounts.iter();
let question_account = next_account_info(accs_iter)?;
let question_issuer = next_account_info(accs_iter)?;
let spl_mint = next_account_info(accs_iter)?;
let issuer_spl_account = next_account_info(accs_iter)?;
let yesno_spl_owner = next_account_info(accs_iter)?;
let spl_account = next_account_info(accs_iter)?;
Self::check_owner_and_signer(program_id, vec![question_account], vec![question_issuer])?;
let mut q = YesNoQuestion::unpack_check_duplicated(&question_account.data.borrow())?;
let pool: u64 = 100;
q.setup(title, deadline, pool, question_issuer.key)?;
q.serialize(&mut &mut question_account.data.borrow_mut()[..])?;
invoke(
&spl_token::instruction::mint_to(
&spl_token::id(),
spl_mint.key,
issuer_spl_account.key,
yesno_spl_owner.key,
&[yesno_spl_owner.key],
pool,
)?,
&[
spl_account.clone(),
spl_mint.clone(),
issuer_spl_account.clone(),
yesno_spl_owner.clone(),
],
)?;
Ok(())
}
pub fn process_bet(program_id: &Pubkey, accounts: &[AccountInfo], yesno: u8) -> ProgramResult {
let accs_iter = &mut accounts.iter();
let bet_account = next_account_info(accs_iter)?;
let question_account = next_account_info(accs_iter)?;
let bet_maker = next_account_info(accs_iter)?;
Self::check_owner_and_signer(program_id, vec![question_account], vec![bet_maker])?;
if bet_account.owner != question_account.key {
return Err(ProgramError::IllegalOwner);
}
let mut bet = Bet::unpack_unchecked(&bet_account.data.borrow())?;
bet.setup(question_account.key, yesno)?;
let mut question = YesNoQuestion::unpack(&question_account.data.borrow())?;
question.add(yesno)?;
bet.serialize(&mut &mut bet_account.data.borrow_mut()[..])?;
question.serialize(&mut &mut question_account.data.borrow_mut()[..])?;
Ok(())
}
pub fn process_close_question(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
Ok(())
}
fn check_owner_and_signer(
owner: &Pubkey,
owner_accounts: Vec<&AccountInfo>,
signers: Vec<&AccountInfo>,
) -> ProgramResult {
for acc in owner_accounts.iter() {
if acc.owner != owner {
return Err(ProgramError::IllegalOwner);
}
}
for acc in signers.iter() {
if !acc.is_signer {
return Err(ProgramError::MissingRequiredSignature);
}
}
return Ok(());
}
}