use anchor_lang::{
prelude::*, solana_program::clock::Clock, solana_program::instruction::Instruction,
};
use super::Statistics;
#[account]
pub struct Task {
pub bundles: Vec<InstructionBundle>,
pub status: TaskStatus,
pub authority: Pubkey,
pub created_at: i64,
pub updated_at: i64,
pub usage_stats: Statistics,
pub own_index: u8,
pub parent_trigger: Pubkey,
pub lut: Option<Pubkey>,
}
impl Task {
pub const MIN_SIZE: usize = 1
+ 1
+ 8
+ 8
+ 32
+ 32
+ 1
+ 1
+ 32
+ 4
+ SerializableInstruction::MIN_SIZE
+ Statistics::MIN_SIZE;
pub fn get_size(instructions: Vec<SerializableInstruction>) -> usize {
let mut size = Self::MIN_SIZE;
size += instructions.len() * SerializableInstruction::MIN_SIZE;
size
}
pub fn new(&self, own_index: u8, trigger: &Pubkey) -> Result<Self> {
Ok(Self {
authority: self.authority, status: self.status,
bundles: self.bundles.to_vec(),
created_at: Clock::get()?.unix_timestamp,
updated_at: Clock::get()?.unix_timestamp,
usage_stats: Statistics::new(),
own_index,
lut: None,
parent_trigger: *trigger,
})
}
pub fn collect_all_accounts(task: &Task) -> Vec<Pubkey> {
let mut all_accounts = Vec::new();
for bundle in &task.bundles {
for instruction in &bundle.instructions {
for account in &instruction.accounts {
all_accounts.push(account.pubkey.clone());
}
}
}
all_accounts
}
}
#[derive(AnchorSerialize, AnchorDeserialize, Clone, PartialEq, Eq, Debug, Copy)]
pub enum TaskStatus {
Incomplete,
Complete,
Partial,
Executed,
Failed,
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug, Hash, PartialEq, Default)]
pub struct InstructionBundle {
pub instructions: Vec<SerializableInstruction>,
pub ready: bool,
pub expiration_slot: Option<u64>,
pub executed: bool,
pub instruction_type: String,
pub args: Option<Args>,
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug, Hash, PartialEq, Default)]
pub struct Args {
pub program_id: Pubkey,
pub data: Vec<u8>,
}
impl InstructionBundle {
pub const MIN_SIZE: usize = 8 + 1 + 1 + 1 + 8 + SerializableInstruction::MIN_SIZE + 40;
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug, Hash, PartialEq, Default)]
pub struct SerializableInstruction {
pub program_id: Pubkey, pub accounts: Vec<SerializableAccount>, pub data: Vec<u8>, }
impl SerializableInstruction {
pub const MIN_SIZE: usize = 32 + 4 + (SerializableAccount::MIN_SIZE * 2);
}
impl From<Instruction> for SerializableInstruction {
fn from(instruction: Instruction) -> Self {
SerializableInstruction {
program_id: instruction.program_id,
accounts: instruction
.accounts
.iter()
.map(|a| SerializableAccount {
pubkey: a.pubkey,
is_signer: a.is_signer,
is_writable: a.is_writable,
})
.collect(),
data: instruction.data,
}
}
}
impl From<&SerializableInstruction> for Instruction {
fn from(instruction: &SerializableInstruction) -> Self {
Instruction {
program_id: instruction.program_id,
accounts: instruction
.accounts
.iter()
.map(|a| AccountMeta {
pubkey: a.pubkey,
is_signer: a.is_signer,
is_writable: a.is_writable,
})
.collect(),
data: instruction.data.clone(),
}
}
}
#[derive(AnchorDeserialize, AnchorSerialize, Clone, Debug, Hash, PartialEq)]
pub struct SerializableAccount {
pub pubkey: Pubkey,
pub is_signer: bool,
pub is_writable: bool,
}
impl SerializableAccount {
pub const MIN_SIZE: usize = 32 + 1 + 1;
pub fn mutable(pubkey: Pubkey, signer: bool) -> Self {
Self {
pubkey,
is_signer: signer,
is_writable: true,
}
}
pub fn readonly(pubkey: Pubkey, signer: bool) -> Self {
Self {
pubkey,
is_signer: signer,
is_writable: false,
}
}
}