use crate::errors::TriggrError;
use crate::state::*;
use anchor_lang::prelude::*;
use anchor_lang::solana_program::pubkey;
use anchor_lang::system_program::{transfer, Transfer};
#[derive(Accounts)]
pub struct PopulateInstruction<'info> {
#[account()]
signer: Signer<'info>,
#[account(mut, seeds = ["payer".as_bytes(), &task.authority.key().to_bytes()[..]], bump)]
payer: UncheckedAccount<'info>,
#[account(mut, seeds = ["task".as_bytes(), &task.parent_trigger.key().to_bytes()[..], &task.own_index.to_le_bytes()[..]], bump)]
task: Box<Account<'info, Task>>,
#[account(owner = pubkey!("2rYeU7ibwWSVFrw29hRtRpnDvBSgUrz8HBQYYnzFKpkt"))]
instruction_account: UncheckedAccount<'info>,
system_program: Program<'info, System>,
}
pub fn handler(ctx: Context<PopulateInstruction>, ix_index: u8) -> Result<()> {
let payer_seeds = &[
"payer".as_bytes(),
&ctx.accounts.task.authority.to_bytes()[..],
&[ctx.bumps["payer"]],
];
let account = ctx.accounts.instruction_account.try_borrow_mut_data()?;
let storage_account = TempStore::try_deserialize(&mut account.as_ref()).unwrap();
let buffer = storage_account.construct_complete_buffer();
let content = TempInstructions::try_deserialize(&mut &*buffer.as_slice())?;
let formated_payer_seeds = &[&payer_seeds[..]];
let task_seeds = &[
"task".as_bytes(),
&ctx.accounts.task.parent_trigger.to_bytes()[..],
&[ctx.accounts.task.own_index],
&[ctx.bumps["task"]],
];
let formated_task_seeds = &[&task_seeds[..]];
let mut next_task = *ctx.accounts.task.clone();
next_task.bundles[ix_index as usize].instructions = content.bundles.clone();
let new_len = next_task.try_to_vec()?.len() + 50;
let task_acc_info = ctx.accounts.task.to_account_info();
let rent = Rent::get()?;
let new_minimum_balance = rent.minimum_balance(new_len);
let current_balance = task_acc_info.lamports();
let diff = new_minimum_balance.checked_sub(current_balance).unwrap();
if diff > 0 {
let cpi_context = CpiContext::new_with_signer(
ctx.accounts.system_program.to_account_info(),
Transfer {
from: ctx.accounts.payer.to_account_info(),
to: ctx.accounts.task.to_account_info(),
},
formated_payer_seeds,
);
transfer(cpi_context, diff)?;
task_acc_info.realloc(new_len, true)?;
} else {
let cpi_context = CpiContext::new_with_signer(
ctx.accounts.system_program.to_account_info(),
Transfer {
from: ctx.accounts.task.to_account_info(),
to: ctx.accounts.payer.to_account_info(),
},
formated_task_seeds,
);
transfer(cpi_context, diff)?;
task_acc_info.realloc(new_len, true)?;
}
assert_eq!(
*ctx.accounts.signer.to_account_info().owner,
pubkey!("2rYeU7ibwWSVFrw29hRtRpnDvBSgUrz8HBQYYnzFKpkt")
);
if ctx.accounts.task.bundles[ix_index as usize].ready {
return Err(TriggrError::InvalidPopulate.into());
}
ctx.accounts.task.bundles[ix_index as usize].instructions = content.bundles.clone();
ctx.accounts.task.bundles[ix_index as usize].ready = true;
let current_slot = Clock::get()?.slot;
msg!("Current slot: {}", current_slot);
ctx.accounts.task.bundles[ix_index as usize].expiration_slot = Some(current_slot + 120);
if ctx.accounts.task.bundles.iter().all(|ix| ix.ready) {
ctx.accounts.task.status = TaskStatus::Complete;
} else {
ctx.accounts.task.status = TaskStatus::Incomplete;
}
Ok(())
}