use bonfida_utils::checks::check_account_owner;
use crate::{
state::record_header::RecordHeader,
utils::{check_domain_owner, get_record_key_and_seeds},
};
use {
crate::cpi,
bonfida_utils::{
checks::{check_account_key, check_signer},
BorshSize, InstructionsAccount,
},
borsh::{BorshDeserialize, BorshSerialize},
solana_program::{
account_info::{next_account_info, AccountInfo},
entrypoint::ProgramResult,
program_error::ProgramError,
pubkey::Pubkey,
},
};
#[derive(BorshDeserialize, BorshSerialize, BorshSize)]
pub struct Params {
pub content_length: u32,
pub record: String,
}
#[derive(InstructionsAccount)]
pub struct Accounts<'a, T> {
pub system_program: &'a T,
pub spl_name_service_program: &'a T,
#[cons(writable, signer)]
pub fee_payer: &'a T,
#[cons(writable)]
pub record: &'a T,
#[cons(writable)]
pub domain: &'a T,
#[cons(writable, signer)]
pub domain_owner: &'a T,
pub central_state: &'a T,
}
impl<'a, 'b: 'a> Accounts<'a, AccountInfo<'b>> {
pub fn parse(accounts: &'a [AccountInfo<'b>]) -> Result<Self, ProgramError> {
let accounts_iter = &mut accounts.iter();
let accounts = Accounts {
system_program: next_account_info(accounts_iter)?,
spl_name_service_program: next_account_info(accounts_iter)?,
fee_payer: next_account_info(accounts_iter)?,
record: next_account_info(accounts_iter)?,
domain: next_account_info(accounts_iter)?,
domain_owner: next_account_info(accounts_iter)?,
central_state: next_account_info(accounts_iter)?,
};
check_account_key(
accounts.system_program,
&solana_system_interface::program::ID,
)?;
check_account_key(accounts.spl_name_service_program, &spl_name_service::ID)?;
check_account_key(accounts.central_state, &crate::central_state::KEY)?;
check_account_owner(accounts.record, &solana_system_interface::program::ID)?;
check_account_owner(accounts.domain, &spl_name_service::ID)?;
check_signer(accounts.fee_payer)?;
check_signer(accounts.domain_owner)?;
Ok(accounts)
}
}
pub fn process(_program_id: &Pubkey, accounts: &[AccountInfo], params: Params) -> ProgramResult {
let accounts = Accounts::parse(accounts)?;
check_domain_owner(accounts.domain, accounts.domain_owner.key)?;
let hashed = crate::utils::get_hashed_name(params.record.as_str());
let (key, _) = get_record_key_and_seeds(accounts.domain.key, ¶ms.record);
check_account_key(accounts.record, &key)?;
cpi::allocate_record(
params.content_length + RecordHeader::LEN as u32,
&hashed,
accounts.record,
accounts.fee_payer,
accounts.domain,
accounts.domain_owner,
accounts.central_state,
accounts.system_program,
)?;
Ok(())
}