sol_chainsaw/
utils.rs

1use solana_program::{hash::hash, pubkey::Pubkey};
2
3use crate::{ChainsawResult, IdlProvider};
4
5pub type DiscriminatorBytes = [u8; 8];
6
7/// Derives the account discriminator form the account name using the same algorithm that anchor
8/// uses.
9pub 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
19/// Resolves the address of the account where the program [IDL] is stored.
20///
21/// - [provider] that uploaded the [IDL]
22/// - [program_id] address of the program
23pub 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}