use {
crate::{
address_lookup_table::program::id,
clock::Slot,
instruction::{AccountMeta, Instruction},
pubkey::Pubkey,
system_program,
},
serde::{Deserialize, Serialize},
};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub enum ProgramInstruction {
CreateLookupTable {
recent_slot: Slot,
bump_seed: u8,
},
FreezeLookupTable,
ExtendLookupTable { new_addresses: Vec<Pubkey> },
DeactivateLookupTable,
CloseLookupTable,
}
pub fn derive_lookup_table_address(
authority_address: &Pubkey,
recent_block_slot: Slot,
) -> (Pubkey, u8) {
Pubkey::find_program_address(
&[authority_address.as_ref(), &recent_block_slot.to_le_bytes()],
&id(),
)
}
fn create_lookup_table_common(
authority_address: Pubkey,
payer_address: Pubkey,
recent_slot: Slot,
authority_is_signer: bool,
) -> (Instruction, Pubkey) {
let (lookup_table_address, bump_seed) =
derive_lookup_table_address(&authority_address, recent_slot);
let instruction = Instruction::new_with_bincode(
id(),
&ProgramInstruction::CreateLookupTable {
recent_slot,
bump_seed,
},
vec![
AccountMeta::new(lookup_table_address, false),
AccountMeta::new_readonly(authority_address, authority_is_signer),
AccountMeta::new(payer_address, true),
AccountMeta::new_readonly(system_program::id(), false),
],
);
(instruction, lookup_table_address)
}
pub fn create_lookup_table_signed(
authority_address: Pubkey,
payer_address: Pubkey,
recent_slot: Slot,
) -> (Instruction, Pubkey) {
create_lookup_table_common(authority_address, payer_address, recent_slot, true)
}
pub fn create_lookup_table(
authority_address: Pubkey,
payer_address: Pubkey,
recent_slot: Slot,
) -> (Instruction, Pubkey) {
create_lookup_table_common(authority_address, payer_address, recent_slot, false)
}
pub fn freeze_lookup_table(lookup_table_address: Pubkey, authority_address: Pubkey) -> Instruction {
Instruction::new_with_bincode(
id(),
&ProgramInstruction::FreezeLookupTable,
vec![
AccountMeta::new(lookup_table_address, false),
AccountMeta::new_readonly(authority_address, true),
],
)
}
pub fn extend_lookup_table(
lookup_table_address: Pubkey,
authority_address: Pubkey,
payer_address: Option<Pubkey>,
new_addresses: Vec<Pubkey>,
) -> Instruction {
let mut accounts = vec![
AccountMeta::new(lookup_table_address, false),
AccountMeta::new_readonly(authority_address, true),
];
if let Some(payer_address) = payer_address {
accounts.extend([
AccountMeta::new(payer_address, true),
AccountMeta::new_readonly(system_program::id(), false),
]);
}
Instruction::new_with_bincode(
id(),
&ProgramInstruction::ExtendLookupTable { new_addresses },
accounts,
)
}
pub fn deactivate_lookup_table(
lookup_table_address: Pubkey,
authority_address: Pubkey,
) -> Instruction {
Instruction::new_with_bincode(
id(),
&ProgramInstruction::DeactivateLookupTable,
vec![
AccountMeta::new(lookup_table_address, false),
AccountMeta::new_readonly(authority_address, true),
],
)
}
pub fn close_lookup_table(
lookup_table_address: Pubkey,
authority_address: Pubkey,
recipient_address: Pubkey,
) -> Instruction {
Instruction::new_with_bincode(
id(),
&ProgramInstruction::CloseLookupTable,
vec![
AccountMeta::new(lookup_table_address, false),
AccountMeta::new_readonly(authority_address, true),
AccountMeta::new(recipient_address, false),
],
)
}