---
title: Account Setup
description: Set up test accounts and state with litesvm-go
---

Demonstrates seeding account state directly with `SetAccount`, without executing
transactions. This is significantly faster than airdropping + funding through
the runtime when you need many accounts ready for a test.

## Basic Account Setup

```go
package mytest

import (
    "testing"

    litesvm "github.com/LiteSVM/litesvm-go"
    solana "github.com/gagliardetto/solana-go"
)

func TestBasicAccountSetup(t *testing.T) {
    svm, err := litesvm.New()
    if err != nil {
        t.Fatal(err)
    }
    defer svm.Close()

    // Calculate minimum balance for rent exemption.
    accountData := []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    minBalance, err := svm.MinimumBalanceForRentExemption(len(accountData))
    if err != nil {
        t.Fatal(err)
    }
    t.Logf("minimum balance for %d bytes: %d lamports", len(accountData), minBalance)

    // Owner program (system program in this trivial example).
    owner := solana.SystemProgramID
    testAddr := solana.NewWallet().PublicKey()

    // Build the account handle, then store it.
    acct, err := litesvm.NewAccount(minBalance, accountData, owner, false, 0)
    if err != nil {
        t.Fatal(err)
    }
    defer acct.Close()

    if err := svm.SetAccount(testAddr, acct); err != nil {
        t.Fatal(err)
    }
    t.Log("account state set successfully")

    // Retrieve the account back.
    retrieved := svm.GetAccount(testAddr)
    if retrieved == nil {
        t.Fatal("expected account to exist")
    }
    defer retrieved.Close()

    t.Logf("  address:    %s", testAddr)
    t.Logf("  lamports:   %d", retrieved.Lamports())
    t.Logf("  owner:      %s", retrieved.Owner())
    t.Logf("  executable: %v", retrieved.Executable())
    t.Logf("  data:       %v", retrieved.Data())

    // Or just read the balance.
    bal, _, err := svm.Balance(testAddr)
    if err != nil {
        t.Fatal(err)
    }
    t.Logf("balance: %d lamports", bal)
}
```

## Setting Up Multiple Accounts

```go
func TestMultipleAccounts(t *testing.T) {
    svm, err := litesvm.New()
    if err != nil {
        t.Fatal(err)
    }
    defer svm.Close()

    owner := solana.SystemProgramID

    // Set up 5 accounts with different data payloads.
    addrs := make([]solana.PublicKey, 5)
    for i := range addrs {
        addrs[i] = solana.NewWallet().PublicKey()

        data := []byte{byte(i), byte(i + 1), byte(i + 2)}
        rent, err := svm.MinimumBalanceForRentExemption(len(data))
        if err != nil {
            t.Fatal(err)
        }

        acct, err := litesvm.NewAccount(rent, data, owner, false, 0)
        if err != nil {
            t.Fatal(err)
        }
        if err := svm.SetAccount(addrs[i], acct); err != nil {
            acct.Close()
            t.Fatal(err)
        }
        acct.Close()

        t.Logf("account %d: %s", i, addrs[i])
    }

    // Verify each account.
    for i, addr := range addrs {
        a := svm.GetAccount(addr)
        if a == nil {
            t.Fatalf("account %d missing", i)
        }
        t.Logf("  account %d: %d lamports, data[0]=%d", i, a.Lamports(), a.Data()[0])
        a.Close()
    }
}
```

## Program Data Account Setup

Set up a program-owned data account by serializing your struct layout into the
account `data`. This snippet additionally imports `encoding/binary`:

```go
import "encoding/binary"

func TestProgramDataAccount(t *testing.T) {
    svm, err := litesvm.New()
    if err != nil {
        t.Fatal(err)
    }
    defer svm.Close()

    programID := solana.NewWallet().PublicKey()
    dataAddr := solana.NewWallet().PublicKey()

    // Example layout: [u8 discriminator, u64 counter, 32-byte owner pubkey]
    data := make([]byte, 1+8+32)
    data[0] = 0x01                                      // discriminator
    binary.LittleEndian.PutUint64(data[1:9], 100)       // counter
    // copy(data[9:], ownerPubkey[:])                   // owner

    rent, err := svm.MinimumBalanceForRentExemption(len(data))
    if err != nil {
        t.Fatal(err)
    }

    acct, err := litesvm.NewAccount(rent, data, programID, false, 0)
    if err != nil {
        t.Fatal(err)
    }
    defer acct.Close()

    if err := svm.SetAccount(dataAddr, acct); err != nil {
        t.Fatal(err)
    }

    t.Logf("program data account set up: %s", dataAddr)
}
```

<Callout type="info">
  `SetAccount` is faster than executing transactions for bulk account setup, and
  keeps your test code focused on the behavior being tested rather than the
  plumbing to construct state.
</Callout>

## Key Points

1. **Direct state** - `SetAccount` writes account state without going through
   the runtime.
2. **Rent exemption** - use `MinimumBalanceForRentExemption` to compute lamports
   before constructing the account.
3. **Ownership** - `NewAccount` returns a handle you still own. The SVM keeps
   its own copy after `SetAccount`; close yours when done.
4. **Verification** - use `GetAccount` to read back into a handle, or `Balance`
   for a lamports-only check.
