---
title: Reading from Network
description:
  Learn how to read data from the Solana blockchain network. This guide covers
  fetching wallet accounts, program accounts, and token mint accounts using
  JavaScript/TypeScript, with practical examples using the Solana web3.js
  library.
---

Now, let's explore how to read data from the Solana network. We'll fetch a few
different accounts to understand the structure of a Solana account.

On Solana, all data is contained in what we call "accounts". You can think of
data on Solana as a public database with a single "Accounts" table, where each
entry in this table is an individual account with the same base
[Account type](https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/account/src/lib.rs#L48-L60).

![Accounts](/assets/docs/core/accounts/accounts.png)

Accounts on Solana can store "state" or "executable" programs, all of which can
be thought of as entries in the same "Accounts" table. Each account has an
"address" (public key) that serves as its unique ID used to locate its
corresponding on-chain data.

Solana accounts contain either:

- State: This is data that's meant to be read from and persisted. It could be
  information about tokens, user data, or any other type of data defined within
  a program.
- Executable Programs: These are accounts that contain the actual code of Solana
  programs. They contain the instructions that can be executed on the network.

This separation of program code and program state is a key feature of Solana's
Account Model. For more details, refer to the
[Solana Account Model](/docs/core/accounts) page.

## Fetch Playground Wallet

Let's start by looking at a familiar account - your own Playground Wallet! We'll
fetch this account and examine its structure to understand what a basic Solana
account looks like.

<Steps>
<Step>

### Open Example

Click this [link](https://beta.solpg.io/6671c5e5cffcf4b13384d198) to open the
example in Solana Playground. You'll see the following code:

```ts title="client.ts"
const address = pg.wallet.publicKey;
const accountInfo = await pg.connection.getAccountInfo(address);

console.log(JSON.stringify(accountInfo, null, 2));
```

<Accordions>
<Accordion title="Explanation">

This code does three simple things:

- Gets your Playground wallet's address

  ```ts
  const address = pg.wallet.publicKey;
  ```

- Fetches the `AccountInfo` for the account at that address

  ```ts
  const accountInfo = await pg.connection.getAccountInfo(address);
  ```

- Prints out the `AccountInfo` to the Playground terminal

  ```ts
  console.log(JSON.stringify(accountInfo, null, 2));
  ```

</Accordion>
</Accordions>

</Step>
<Step>

### Run Example

In the Playground terminal, type the `run` command and hit enter:

```shell title="Terminal"
run
```

When you run the code, you'll see the account details for your wallet displayed
in the terminal. The output should look similar to the following:

<Accordions>
<Accordion title="Output">

```shell title="Terminal"
$ run
Running client...
  client.ts:
    {
  "data": {
    "type": "Buffer",
    "data": []
  },
  "executable": false,
  "lamports": 5000000000,
  "owner": "11111111111111111111111111111111",
  "rentEpoch": 18446744073709552000,
  "space": 0
}
```

</Accordion>
<Accordion title="Explanation">

Your wallet is actually an account owned by the
[System Program](https://github.com/anza-xyz/agave/tree/v2.1.11/programs/system),
one of Solana's native programs. The main purpose of the wallet account is to
store your SOL balance (amount in the `lamports` field).

At its core, all Solana accounts are just bytes that deserialize into the same
base
[Account type](https://github.com/anza-xyz/agave/blob/v2.1.11/sdk/account/src/lib.rs#L48-L60).

Let's break down the fields in the output:

- `data` - This field contains what we generally refer to as the account "data".
  For a wallet, it's empty (0 bytes), but other accounts use this field to store
  any arbitrary data as a serialized buffer of bytes.

- `executable` - A flag that indicates whether the account is an executable
  program. For wallets and any accounts that store state, this is `false`.
- `owner` - This field shows which program controls the account. For wallets,
  it's always the System Program, with the address
  `11111111111111111111111111111111`.
- `lamports` - The account's balance in lamports (1 SOL = 1,000,000,000
  lamports).
- `rentEpoch` - A legacy field related to Solana's deprecated rent collection
  mechanism (currently not in use).
- `space` - Indicates byte capacity (length) of the `data` field (not a field in
  the `Account` type)

</Accordion>
</Accordions>

</Step>
</Steps>

## Fetch Token Program

Next, we'll examine the Token Extensions program, an executable program for
interacting with tokens on Solana.

<Steps>
<Step>

### Open Example

Click this [link](https://beta.solpg.io/6671c6e7cffcf4b13384d199) to open the
example in Solana Playground. You'll see the following code:

```ts title="client.ts" {3}
import { PublicKey } from "@solana/web3.js";

const address = new PublicKey("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");
const accountInfo = await pg.connection.getAccountInfo(address);

console.log(JSON.stringify(accountInfo, null, 2));
```

Instead of fetching your Playground wallet, here we fetch the Token Extensions
Program account.

</Step>
<Step>

### Run Example

Run the code using the `run` command in the terminal.

```shell title="Terminal"
run
```

Examine the output and how this program account differs from your wallet
account.

<Accordions>
<Accordion title="Output">

```shell title="Terminal" {15, 17}
$ run
Running client...
  client.ts:
    {
  "data": {
    "type": "Buffer",
    "data": [
      2,
      0,
      //... additional bytes
      86,
      51
    ]
  },
  "executable": true,
  "lamports": 1141440,
  "owner": "BPFLoaderUpgradeab1e11111111111111111111111",
  "rentEpoch": 18446744073709552000,
  "space": 36
}
```

</Accordion>
<Accordion title="Explanation">

The Token Extensions program is an executable program account, but note that it
has the same `Account` structure.

Key differences to note from the output:

- `executable` - Set to `true`, indicating this account represents an executable
  program.
- `data` - Contains serialized data (unlike the empty data in a wallet account).
  The data for a program account stores the address of another account (Program
  Executable Data Account) that contains the program's bytecode.
- `owner` - The account is owned by the Upgradable BPF Loader
  (`BPFLoaderUpgradeab1e11111111111111111111111`), a native program that manages
  executable accounts.

You can inspect the Solana Explorer for the
[Token Extensions Program Account](https://explorer.solana.com/address/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb)
and its corresponding
[Program Executable Data Account](https://explorer.solana.com/address/DoU57AYuPFu2QU514RktNPG22QhApEjnKxnBcu4BHDTY).

The Program Executable Data Account contains the compiled bytecode for the Token
Extensions Program
[source code](https://github.com/solana-program/token-2022/tree/main/program).

</Accordion>
</Accordions>

</Step>
</Steps>

## Fetch Mint Account

In this step, we'll examine a Mint account, which represents a unique token on
the Solana network.

<Steps>
<Step>

### Open Example

Click this [link](https://beta.solpg.io/6671c9aecffcf4b13384d19a) to open the
example in Solana Playground. You'll see the following code:

```ts title="client.ts" {3}
import { PublicKey } from "@solana/web3.js";

const address = new PublicKey("C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR");
const accountInfo = await pg.connection.getAccountInfo(address);

console.log(JSON.stringify(accountInfo, null, 2));
```

In this example, we'll fetch the address of an existing Mint account on devnet.

</Step>
<Step>

### Run Example

Run the code using the `run` command.

```shell title="Terminal"
run
```

<Accordions>
<Accordion title="Output">

```shell title="Terminal" {17}
$ run
Running client...
  client.ts:
    {
  "data": {
    "type": "Buffer",
    "data": [
      1,
      0,
      //... additional bytes
      0,
      0
    ]
  },
  "executable": false,
  "lamports": 4176000,
  "owner": "TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb",
  "rentEpoch": 18446744073709552000,
  "space": 430
}
```

</Accordion>
<Accordion title="Explanation">

Key differences to note from the output:

- `owner` - The mint account is owned by the Token Extensions program
  (`TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb`).
- `executable` - Set to `false`, as this account stores state rather than
  executable code.
- `data`: Contains serialized data about the token (mint authority, supply,
  decimals, etc.).

</Accordion>
</Accordions>

</Step>
<Step>

### Deserialize Mint Account Data

An account's `data` field contains bytes that need to be further deserialized
into the expected data type. The structure of this data is defined by the
program that owns the account.

To help with deserialization, most program developers provide helper functions
in their client libraries that handle converting the raw bytes into the
appropriate data type.

For example, the `@solana/spl-token` library provides functions like `getMint()`
to help deserialize a token mint account's bytes into the
[Mint](https://github.com/solana-program/token-2022/blob/rust-legacy%40v0.14.0/program/src/state.rs#L30-L44)
data type.

Open this next [example](https://beta.solpg.io/679d4c99cffcf4b13384d601) in
Solana Playground. You'll see the following code:

```ts title="client.ts"
import { PublicKey } from "@solana/web3.js";
import { getMint, TOKEN_2022_PROGRAM_ID } from "@solana/spl-token";

const address = new PublicKey("C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR");
const mintData = await getMint(
  pg.connection,
  address,
  "confirmed",
  TOKEN_2022_PROGRAM_ID,
);

console.log(
  JSON.stringify(
    mintData,
    (key, value) => {
      // Convert BigInt to String
      if (typeof value === "bigint") {
        return value.toString();
      }
      // Handle Buffer objects
      if (Buffer.isBuffer(value)) {
        return `<Buffer ${value.toString("hex")}>`;
      }
      return value;
    },
    2,
  ),
);
```

This example uses the `getMint` helper function to automatically deserialize the
data field of the Mint account.

Run the code using the `run` command.

```shell title="Terminal"
run
```

You should see the following deserialized Mint account data.

<Accordions>
<Accordion title="Output">

```shell title="Terminal"
$ run
Running client...
  client.ts:
    {
  "address": "C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR",
  "mintAuthority": "3z9vL1zjN6qyAFHhHQdWYRTFAcy69pJydkZmSFBKHg1R",
  "supply": "0",
  "decimals": 2,
  "isInitialized": true,
  "freezeAuthority": null,
  "tlvData": {
    "type": "Buffer",
    "data": [
      18,
      0,
      //... additional bytes
      0,
      0
    ]
  }
}
```

</Accordion>
<Accordion title="Explanation">

The `getMint` function deserializes the account data into the
[Mint](https://github.com/solana-labs/solana-program-library/blob/b1c44c171bc95e6ee74af12365cb9cbab68be76c/token/program/src/state.rs#L18-L32)
data type defined in the Token Extensions program source code.

- `address` - The Mint account's address
- `mintAuthority` - The authority allowed to mint new tokens
- `supply` - The total supply of tokens
- `decimals` - The number of decimal places for the token
- `isInitialized` - Whether the Mint data has been initialized
- `freezeAuthority` - The authority allowed to freeze token accounts
- `tlvData` - Additional data for Token Extensions (requires further
  deserialization)

You can view the fully deserialized
[Mint Account](https://explorer.solana.com/address/C33qt1dZGZSsqTrHdtLKXPZNoxs6U1ZBfyDkzmj6mXeR?cluster=devnet)
data, including enabled Token Extensions, on the Solana Explorer.

</Accordion>
</Accordions>

</Step>
</Steps>
