use solana_program::{hash::hash, pubkey::Pubkey};
use crate::{ChainsawResult, IdlProvider};
pub type DiscriminatorBytes = [u8; 8];
pub fn account_discriminator(name: &str) -> DiscriminatorBytes {
let mut discriminator = [0u8; 8];
let hashed = hash(format!("account:{}", name).as_bytes()).to_bytes();
discriminator.copy_from_slice(&hashed[..8]);
discriminator
}
const ANCHOR_SEED: &str = "anchor:idl";
const SHANK_SEED: &str = "shank:idl";
pub fn try_idl_address(
provider: &IdlProvider,
program_id: &Pubkey,
) -> ChainsawResult<Pubkey> {
let (base, _) = Pubkey::find_program_address(&[], program_id);
let seed = match provider {
IdlProvider::Anchor => ANCHOR_SEED,
IdlProvider::Shank => SHANK_SEED,
};
let key = Pubkey::create_with_seed(&base, seed, program_id)?;
Ok(key)
}
#[cfg(test)]
mod test {
use std::str::FromStr;
use super::*;
pub fn str_to_pubkey(pubkey_str: &str) -> Pubkey {
FromStr::from_str(pubkey_str).expect("pubkey from string")
}
#[test]
fn account_discriminator_test() {
let name = "VaultInfo";
let discriminator = account_discriminator(name);
assert_eq!(discriminator, [133, 250, 161, 78, 246, 27, 55, 187]);
}
#[test]
fn idl_address_test() {
let program_id =
str_to_pubkey("cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ");
let anchor_idl_address =
try_idl_address(&IdlProvider::Anchor, &program_id).unwrap();
let shank_idl_address =
try_idl_address(&IdlProvider::Shank, &program_id).unwrap();
assert_eq!(
anchor_idl_address.to_string(),
"CggtNXgCye2qk7fLohonNftqaKT35GkuZJwHrRghEvSF"
);
assert_eq!(
shank_idl_address.to_string(),
"AEUhdmwzSea7oYDWhAiSBArqq6tBLFNNZZ448wfbaV3Z"
);
}
}