tensor_eigen/
discriminators.rs

1use anyhow::{anyhow, Result};
2use borsh::BorshDeserialize;
3use sha2::{Digest, Sha256};
4use tensor_amm::accounts::{NftDepositReceipt, Pool};
5use tensor_marketplace::accounts::{BidState, ListState};
6use tensor_price_lock::accounts::OrderState;
7use tensor_whitelist::accounts::{MintProof, MintProofV2, Whitelist, WhitelistV2};
8
9use crate::args::AnchorDiscriminatorKind;
10
11pub trait Discriminator {
12    const KIND: AnchorDiscriminatorKind = AnchorDiscriminatorKind::Account;
13
14    fn discriminator() -> [u8; 8] {
15        let prefix = match Self::KIND {
16            AnchorDiscriminatorKind::Account => "account",
17            AnchorDiscriminatorKind::Instruction => "global",
18        };
19
20        let mut hasher = Sha256::new();
21        hasher.update(format!(
22            "{prefix}:{}",
23            std::any::type_name::<Self>()
24                .split("::")
25                .last()
26                .expect("No type name found")
27        ));
28        let result = hasher.finalize();
29        let mut discriminator = [0u8; 8];
30        discriminator.copy_from_slice(&result[..8]);
31        discriminator
32    }
33}
34
35pub fn deserialize_account<T: BorshDeserialize + Discriminator>(mut data: &[u8]) -> Result<T> {
36    if data.len() < 8 {
37        return Err(anyhow!("Data too short"));
38    }
39
40    let discriminator: [u8; 8] = data[..8].try_into()?;
41    if discriminator != T::discriminator() {
42        return Err(anyhow!("Invalid discriminator for type"));
43    }
44
45    T::deserialize(&mut data).map_err(Into::into)
46}
47
48impl Discriminator for Pool {}
49impl Discriminator for NftDepositReceipt {}
50
51impl Discriminator for Whitelist {}
52impl Discriminator for WhitelistV2 {}
53impl Discriminator for MintProof {}
54impl Discriminator for MintProofV2 {}
55impl Discriminator for BidState {}
56impl Discriminator for ListState {}
57
58impl Discriminator for OrderState {}