use anchor_lang::AccountDeserialize;
use litesvm::LiteSVM;
use solana_program::pubkey::Pubkey;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum AccountError {
#[error("Account not found at address: {0}")]
AccountNotFound(Pubkey),
#[error("Failed to deserialize account: {0}")]
DeserializationError(String),
#[error("Account discriminator mismatch")]
DiscriminatorMismatch,
}
pub fn get_anchor_account<T>(
svm: &LiteSVM,
address: &Pubkey,
) -> Result<T, AccountError>
where
T: AccountDeserialize,
{
let account = svm
.get_account(address)
.ok_or_else(|| AccountError::AccountNotFound(*address))?;
let mut data_slice: &[u8] = &account.data;
T::try_deserialize(&mut data_slice)
.map_err(|e| AccountError::DeserializationError(e.to_string()))
}
pub fn get_anchor_account_unchecked<T>(
svm: &LiteSVM,
address: &Pubkey,
) -> Result<T, AccountError>
where
T: borsh::BorshDeserialize,
{
let account = svm
.get_account(address)
.ok_or_else(|| AccountError::AccountNotFound(*address))?;
if account.data.len() < 8 {
return Err(AccountError::DeserializationError(
"Account data too small for Anchor account".to_string()
));
}
T::try_from_slice(&account.data[8..])
.map_err(|e| AccountError::DeserializationError(e.to_string()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_account_error_display() {
let error = AccountError::AccountNotFound(Pubkey::new_unique());
assert!(error.to_string().contains("Account not found"));
let error = AccountError::DeserializationError("test error".to_string());
assert!(error.to_string().contains("Failed to deserialize"));
let error = AccountError::DiscriminatorMismatch;
assert_eq!(error.to_string(), "Account discriminator mismatch");
}
}