sns-records 0.3.0

Bindings and program code for the Solana Name Service Records protocol
Documentation
use solana_program::{account_info::AccountInfo, hash::hashv, program_pack::Pack};
use spl_name_service::state::NameRecordHeader;
use spl_name_service::state::HASH_PREFIX;

use crate::error::SnsRecordsError;

use {
    solana_program::pubkey, solana_program::pubkey::Pubkey,
    spl_name_service::state::get_seeds_and_key,
};

pub const ROOT_DOMAIN: Pubkey = pubkey!("58PwtjSDuFHuUkYjH9BYnnQKHfwo9reZhC2zMJv9JPkx");

pub fn get_hashed_name(record: &str) -> Vec<u8> {
    hashv(&[(HASH_PREFIX.to_owned() + record).as_bytes()])
        .as_ref()
        .to_vec()
}

pub fn get_record_key_and_seeds(domain: &Pubkey, record: &str) -> (Pubkey, Vec<u8>) {
    let hashed = get_hashed_name(record);
    get_seeds_and_key(
        &spl_name_service::ID,
        hashed,
        Some(&crate::central_state::KEY),
        Some(domain),
    )
}

pub fn check_domain_owner(
    account: &AccountInfo,
    expected_owner: &Pubkey,
) -> Result<(), SnsRecordsError> {
    let hd = NameRecordHeader::unpack_from_slice(&account.data.borrow())
        .map_err(|_| SnsRecordsError::DataTypeMismatch)?;

    if hd.owner != *expected_owner {
        return Err(SnsRecordsError::WrongDomainOwner);
    }

    Ok(())
}

pub fn check_domain_parent(
    account: &AccountInfo,
    expected_parent: &Pubkey,
) -> Result<(), SnsRecordsError> {
    let hd = NameRecordHeader::unpack_from_slice(&account.data.borrow())
        .map_err(|_| SnsRecordsError::DataTypeMismatch)?;

    if hd.class != crate::central_state::KEY {
        return Err(SnsRecordsError::WrongClass);
    }

    if hd.parent_name != *expected_parent {
        return Err(SnsRecordsError::WrongParent);
    }

    Ok(())
}