1use solana_program::{hash::hash, pubkey::Pubkey};
2
3use crate::{ChainsawResult, IdlProvider};
4
5pub type DiscriminatorBytes = [u8; 8];
6
7pub fn account_discriminator(name: &str) -> DiscriminatorBytes {
10 let mut discriminator = [0u8; 8];
11 let hashed = hash(format!("account:{}", name).as_bytes()).to_bytes();
12 discriminator.copy_from_slice(&hashed[..8]);
13 discriminator
14}
15
16const ANCHOR_SEED: &str = "anchor:idl";
17const SHANK_SEED: &str = "shank:idl";
18
19pub fn try_idl_address(
24 provider: &IdlProvider,
25 program_id: &Pubkey,
26) -> ChainsawResult<Pubkey> {
27 let (base, _) = Pubkey::find_program_address(&[], program_id);
28 let seed = match provider {
29 IdlProvider::Anchor => ANCHOR_SEED,
30 IdlProvider::Shank => SHANK_SEED,
31 };
32 let key = Pubkey::create_with_seed(&base, seed, program_id)?;
33 Ok(key)
34}
35
36#[cfg(test)]
37mod test {
38 use std::str::FromStr;
39
40 use super::*;
41
42 pub fn str_to_pubkey(pubkey_str: &str) -> Pubkey {
43 FromStr::from_str(pubkey_str).expect("pubkey from string")
44 }
45
46 #[test]
47 fn account_discriminator_test() {
48 let name = "VaultInfo";
49 let discriminator = account_discriminator(name);
50 assert_eq!(discriminator, [133, 250, 161, 78, 246, 27, 55, 187]);
51 }
52
53 #[test]
54 fn idl_address_test() {
55 let program_id =
56 str_to_pubkey("cndy3Z4yapfJBmL3ShUp5exZKqR3z33thTzeNMm2gRZ");
57
58 let anchor_idl_address =
59 try_idl_address(&IdlProvider::Anchor, &program_id).unwrap();
60 let shank_idl_address =
61 try_idl_address(&IdlProvider::Shank, &program_id).unwrap();
62
63 assert_eq!(
64 anchor_idl_address.to_string(),
65 "CggtNXgCye2qk7fLohonNftqaKT35GkuZJwHrRghEvSF"
66 );
67 assert_eq!(
68 shank_idl_address.to_string(),
69 "AEUhdmwzSea7oYDWhAiSBArqq6tBLFNNZZ448wfbaV3Z"
70 );
71 }
72}