triggr-program 0.1.1

Created with Anchor
Documentation
use crate::errors;
use anchor_lang::prelude::*;
use solana_address_lookup_table_program as solana_lut;
use solana_program::program::invoke_signed;

use super::close_task::Task;
pub use errors::*;

#[derive(Accounts)]
#[instruction(slot: u64, bump: u8)]
pub struct CreateLut<'info> {
    #[account(mut)]
    signer: Signer<'info>,

    /// CHECK: account is owned by system prorgam
    #[account(mut, seeds = ["payer".as_bytes(), &task.authority.key().to_bytes()[..]], bump)]
    payer: UncheckedAccount<'info>,

    /// CHECK: System Program owned account
    #[account(constraint = authority.key() == task.authority.key())]
    authority: UncheckedAccount<'info>,
    //
    /// CHECK: account will be initialized
    #[account(mut, seeds =[&payer.key().to_bytes()[..], &slot.to_le_bytes()[..]], bump, seeds::program = solana_lut::id())]
    lut: UncheckedAccount<'info>,

    #[account(mut, seeds = ["task".as_bytes(), &task.parent_trigger.key().to_bytes()[..], &task.own_index.to_le_bytes()[..]], bump, constraint = task.lut.is_none() @ TriggrError::LookUpTableAlreadyExists)]
    task: Account<'info, Task>,

    /// CHECK: programID
    address_lookup_table_program: UncheckedAccount<'info>,

    system_program: Program<'info, System>,
}

pub fn handler(ctx: Context<CreateLut>, slot: u64, _bump: u8) -> Result<()> {
    let (instruction, _pubkey) = solana_lut::instruction::create_lookup_table(
        ctx.accounts.payer.key(),
        ctx.accounts.payer.key(),
        slot,
    );

    let payer_seeds = &[
        "payer".as_bytes(),
        &ctx.accounts.authority.key().to_bytes()[..],
        &[ctx.bumps["payer"]],
    ];

    let formated_payer_seeds = &[&payer_seeds[..]];

    invoke_signed(
        &instruction,
        &[
            ctx.accounts.lut.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.payer.to_account_info(),
            ctx.accounts.system_program.to_account_info(),
        ],
        formated_payer_seeds,
    )?;

    let accounts = Task::collect_all_accounts(&ctx.accounts.task);
    msg!("accounts: {:?}", accounts.len());

    let account_slice = accounts.as_slice();

    let num_iterations = (account_slice.len() + 26) / 27; // Round up division

    for i in 0..num_iterations {
        let start_index = i * 27;
        let end_index = (i + 1) * 27;
        msg!("iteration: {}", i);
        msg!("start index: {}", start_index);
        msg!("end index: {}", end_index);
        let slice = &account_slice[start_index..end_index.min(account_slice.len())];

        let extend_instruction = solana_lut::instruction::extend_lookup_table(
            ctx.accounts.lut.key(),
            ctx.accounts.payer.key(),
            Some(ctx.accounts.payer.key()),
            slice.to_vec(),
        );

        invoke_signed(
            &extend_instruction,
            &[
                ctx.accounts.lut.to_account_info(),
                ctx.accounts.authority.to_account_info(),
                ctx.accounts.payer.to_account_info(),
            ],
            formated_payer_seeds,
        )?;
    }

    ctx.accounts.task.lut = Some(ctx.accounts.lut.key());
    Ok(())
}