tensor_eigen/
discriminators.rs1use 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 {}