---
title: Account Management
description:
  Fetching and deserializing Anchor accounts with automatic discriminator
  handling
---

## Understanding Anchor Account Discriminators

Anchor programs prepend an 8-byte discriminator to all account data. This
discriminator is a hash of the account type name and is used to verify that
account data matches the expected type.

```
┌─────────────────────────────────────────────────┐
│ Account Data Layout                             │
├────────────────┬────────────────────────────────┤
│ Discriminator  │ Account Fields                 │
│ (8 bytes)      │ (variable size)                │
└────────────────┴────────────────────────────────┘
```

The `anchor-litesvm` account utilities handle this discriminator automatically.

## Fetching Anchor Accounts

### Basic Account Fetching

```rust
use anchor_litesvm::AnchorLiteSVM;
use anchor_lang::prelude::*;
use solana_signer::Signer;
use solana_program::pubkey::Pubkey;

#[account]
pub struct UserAccount {
    pub name: String,
    pub balance: u64,
    pub authority: Pubkey,
}

#[test]
fn test_fetch_account() {
    let mut ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));

    let user = ctx.create_funded_account(10_000_000_000).unwrap();

    // ... initialize the account ...

    let (user_pda, _) = Pubkey::find_program_address(
        &[b"user", user.pubkey().as_ref()],
        &PROGRAM_ID,
    );

    // Fetch and deserialize the account
    let account: UserAccount = ctx.get_account(&user_pda).unwrap();

    assert_eq!(account.name, "Alice");
    assert_eq!(account.authority, user.pubkey());
}
```

<Callout type="info">
  `get_account<T>()` automatically validates the 8-byte discriminator to ensure the account data matches the expected type.
</Callout>

### Unchecked Deserialization

For PDAs or custom account layouts where discriminator validation might fail,
use `get_account_unchecked`:

```rust
use anchor_litesvm::AnchorLiteSVM;

#[test]
fn test_fetch_unchecked() {
    let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));

    // Fetch without discriminator validation
    let account: UserAccount = ctx.get_account_unchecked(&some_pda).unwrap();
}
```

<Callout type="warn">
  Use `get_account_unchecked` carefully. Without discriminator validation, you
  might deserialize invalid data. Only use this when you're certain about the
  account type.
</Callout>

## Using the Account Module Directly

You can also use the account deserialization functions directly:

```rust
use anchor_litesvm::{get_anchor_account, get_anchor_account_unchecked};
use litesvm::LiteSVM;

#[test]
fn test_direct_account_fetch() {
    let mut svm = LiteSVM::new();
    // ... setup ...

    // Fetch with discriminator check
    let account: UserAccount = get_anchor_account(&svm, &account_pubkey).unwrap();

    // Fetch without discriminator check
    let account: UserAccount = get_anchor_account_unchecked(&svm, &account_pubkey).unwrap();
}
```

## Account Errors

The `AccountError` enum provides detailed error information:

```rust
use anchor_litesvm::AccountError;

#[test]
fn test_handle_errors() {
    let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));

    let result: Result<UserAccount, AccountError> = ctx.get_account(&nonexistent_pubkey);

    match result {
        Ok(account) => println!("Found account: {}", account.name),
        Err(AccountError::AccountNotFound(pubkey)) => {
            println!("Account not found: {}", pubkey);
        }
        Err(AccountError::DiscriminatorMismatch) => {
            println!("Wrong account type!");
        }
        Err(AccountError::DeserializationError(msg)) => {
            println!("Failed to deserialize: {}", msg);
        }
    }
}
```

| Error                          | Description                                       |
| ------------------------------ | ------------------------------------------------- |
| `AccountNotFound(Pubkey)`      | No account exists at the given address            |
| `DiscriminatorMismatch`        | Account discriminator doesn't match expected type |
| `DeserializationError(String)` | Failed to deserialize account data                |

## Working with Multiple Account Types

### Fetching Different Account Types

```rust
use anchor_litesvm::AnchorLiteSVM;
use anchor_lang::prelude::*;

#[account]
pub struct Config {
    pub admin: Pubkey,
    pub fee_bps: u16,
}

#[account]
pub struct UserProfile {
    pub owner: Pubkey,
    pub username: String,
    pub created_at: i64,
}

#[account]
pub struct Order {
    pub user: Pubkey,
    pub amount: u64,
    pub status: OrderStatus,
}

#[derive(AnchorSerialize, AnchorDeserialize, Clone)]
pub enum OrderStatus {
    Pending,
    Completed,
    Cancelled,
}

#[test]
fn test_multiple_account_types() {
    let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));

    // Each account type is deserialized correctly
    let config: Config = ctx.get_account(&config_pda).unwrap();
    let profile: UserProfile = ctx.get_account(&profile_pda).unwrap();
    let order: Order = ctx.get_account(&order_pda).unwrap();

    assert_eq!(config.fee_bps, 100);
    assert_eq!(profile.username, "alice");
    assert!(matches!(order.status, OrderStatus::Pending));
}
```

### Checking Account Existence Before Fetching

```rust
use anchor_litesvm::AnchorLiteSVM;

#[test]
fn test_check_before_fetch() {
    let ctx = AnchorLiteSVM::build_with_program(PROGRAM_ID, include_bytes!("../target/deploy/your_program.so"));

    let user_pda = Pubkey::new_unique();

    // Check existence first
    if ctx.account_exists(&user_pda) {
        let account: UserAccount = ctx.get_account(&user_pda).unwrap();
        println!("Found: {}", account.name);
    } else {
        println!("Account not initialized yet");
    }
}
```

## Complete Example

Here's a comprehensive example demonstrating account management:

```rust
use anchor_litesvm::AnchorLiteSVM;
use anchor_litesvm::TestHelpers;
use anchor_lang::prelude::*;
use solana_signer::Signer;
use solana_program::pubkey::Pubkey;

anchor_lang::declare_program!(counter);

#[test]
fn test_counter_workflow() {
    let mut ctx = AnchorLiteSVM::build_with_program(
        id(),
        include_bytes!("../target/deploy/counter.so"),
    );

    let authority = ctx.svm.create_funded_account(10_000_000_000).unwrap();

    // Derive the counter PDA
    let (counter_pda, bump) = Pubkey::find_program_address(
        &[b"counter", authority.pubkey().as_ref()],
        &id(),
    );

    // Verify counter doesn't exist yet
    assert!(!ctx.account_exists(&counter_pda));

    // Initialize using generated client types
    let init_ix = ctx.program()
        .accounts(counter::client::accounts::Initialize {
            authority: authority.pubkey(),
            counter: counter_pda,
            system_program: anchor_lang::system_program::ID,
        })
        .args(counter::client::args::Initialize {})
        .instruction()
        .unwrap();

    ctx.execute_instruction(init_ix, &[&authority]).unwrap();

    // Verify counter exists and has correct initial state
    assert!(ctx.account_exists(&counter_pda));
    let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
    assert_eq!(counter.count, 0);
    assert_eq!(counter.authority, authority.pubkey());
    assert_eq!(counter.bump, bump);

    // Increment using generated client types
    let increment_ix = ctx.program()
        .accounts(counter::client::accounts::Increment {
            authority: authority.pubkey(),
            counter: counter_pda,
        })
        .args(counter::client::args::Increment {})
        .instruction()
        .unwrap();

    ctx.execute_instruction(increment_ix, &[&authority]).unwrap();

    // Verify incremented
    let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
    assert_eq!(counter.count, 1);

    // Increment again
    ctx.execute_instruction(increment_ix.clone(), &[&authority]).unwrap();

    let counter: counter::Counter = ctx.get_account(&counter_pda).unwrap();
    assert_eq!(counter.count, 2);

    println!("Counter test passed! Final count: {}", counter.count);
}
```
