pub mod domain;
pub mod subdomain;
use solana_instruction::{AccountMeta, Instruction};
use solana_program_error::ProgramError;
use solana_pubkey::Pubkey;
use solana_rent::Rent;
use crate::{
SNS_PROGRAM_ID, SNSNode, constants::SNS_RECORD_HEADER_BYTE_LEN,
instruction_builder::NameRegistryInstruction, name_record::SNSNodeWithOwner,
};
#[derive(Debug, Clone, Copy)]
pub struct CreateInstBuilder {
payer: Pubkey,
account: SNSNode,
owner: Option<Pubkey>,
class: Option<Pubkey>,
parent: SNSNodeWithOwner,
space: Option<u32>,
}
impl CreateInstBuilder {
pub fn build(self) -> Result<Instruction, ProgramError> {
let Self {
payer,
account: SNSNode { pda, hashed_name },
owner,
class,
parent: SNSNodeWithOwner { pda: parent, owner: parent_owner },
space,
} = self;
let owner = owner.unwrap_or(payer);
let hashed_name = hashed_name.to_bytes().to_vec();
let space = space.unwrap_or_default();
let lamports = calculate_rent_exemption(space);
let inst = NameRegistryInstruction::Create { hashed_name, lamports, space };
create(SNS_PROGRAM_ID, inst, pda, payer, owner, class, Some(parent), Some(parent_owner))
}
}
pub fn calculate_rent_exemption(bytes: u32) -> u64 {
Rent::default().minimum_balance((bytes as usize).saturating_add(SNS_RECORD_HEADER_BYTE_LEN))
}
#[allow(clippy::too_many_arguments)]
pub fn create(
name_service_program_id: Pubkey,
instruction_data: NameRegistryInstruction,
name_account_key: Pubkey,
payer_key: Pubkey,
name_owner: Pubkey,
name_class_opt: Option<Pubkey>,
name_parent_opt: Option<Pubkey>,
name_parent_owner_opt: Option<Pubkey>,
) -> Result<Instruction, ProgramError> {
let data: Vec<u8> = bincode::serialize(&instruction_data).unwrap();
let mut accounts = vec![
AccountMeta::new_readonly(Pubkey::default(), false), AccountMeta::new(payer_key, true),
AccountMeta::new(name_account_key, false),
AccountMeta::new_readonly(name_owner, false),
];
if let Some(name_class) = name_class_opt {
accounts.push(AccountMeta::new_readonly(name_class, true));
} else {
accounts.push(AccountMeta::new_readonly(Pubkey::default(), false));
}
if let Some(name_parent) = name_parent_opt {
accounts.push(AccountMeta::new_readonly(name_parent, false));
} else {
accounts.push(AccountMeta::new_readonly(Pubkey::default(), false));
}
if let Some(key) = name_parent_owner_opt {
accounts.push(AccountMeta::new_readonly(key, true));
}
Ok(Instruction { program_id: name_service_program_id, accounts, data })
}