Reading from Network

This section explores how to read data from the Solana network by fetching different accounts to understand the structure of a Solana account.

On Solana, all data exists in "accounts". You can think of data on Solana as a public database with a single "Accounts" table, where each entry is an account with the same base Account type.

Base Account Type
#[derive(PartialEq, Eq, Clone, Default)]
pub struct Account {
/// lamports in the account
pub lamports: u64,
/// data held in this account
#[cfg_attr(feature = "serde", serde(with = "serde_bytes"))]
pub data: Vec<u8>,
/// the program that owns this account. If executable, the program that loads this account.
pub owner: Pubkey,
/// this account's data contains a loaded program (and is now read-only)
pub executable: bool,
/// the epoch at which this account will next owe rent
pub rent_epoch: Epoch,
}

AccountsAccounts

Accounts on Solana can store "state" or "executable" programs. 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: Data that meant to be read from and persisted. For example, information about tokens, user data, or other data defined within a program.
  • Executable Programs: Accounts containing the actual code of Solana programs. These accounts store instructions that users can invoke.

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 page.

Fetch Wallet Account

This example demonstrates how to:

  1. Generate a new keypair (public/private key pair).
  2. Request an airdrop of SOL to fund the new address.
  3. Retrieve the account data for the funded address.

On Solana, funding a new address with SOL automatically creates an account owned by the System Program. All "wallet" accounts are simply System Program owned accounts that hold SOL and can sign transactions.

Fetch Account
import { Keypair, Connection, LAMPORTS_PER_SOL } from "@solana/web3.js";
const keypair = Keypair.generate();
console.log(`Public Key: ${keypair.publicKey}`);
const connection = new Connection("http://localhost:8899", "confirmed");
// Funding an address with SOL automatically creates an account
const signature = await connection.requestAirdrop(
keypair.publicKey,
LAMPORTS_PER_SOL
);
await connection.confirmTransaction(signature, "confirmed");
const accountInfo = await connection.getAccountInfo(keypair.publicKey);
console.log(JSON.stringify(accountInfo, null, 2));
Console
Click to execute the code.

A "wallet" on Solana is an account owned by the System Program, which is one of Solana’s built-in programs. Wallet accounts are primarily used to hold SOL (tracked in the lamports field) and to sign transactions.

When you fetch a wallet account, the response includes the fields shown in the example output.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The data field contains the account's data stored as bytes.

For wallet accounts, this field is empty (0 bytes). Other accounts use this field to store either program state or executable program code.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The executable field indicates if the account's data field contains executable program code.

For wallet and accounts that store program state, this field is false.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The lamports field contains the account's SOL balance, denominated in lamports.

Lamports are the smallest unit of SOL. 1 SOL = 1,000,000,000 lamports.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The owner field shows the program that owns the account.

For wallets, the owner is always the System Program, with the address 11111111111111111111111111111111.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The rentEpoch field is a legacy field from a deprecated mechanism where accounts were charged "rent" (in lamports) to maintain its data on the network.

This field is currently unused, but is included for backwards compatibility.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

The space field shows the number of bytes in the data field. This is not a field in the Account type itself, but included in the response.

In this example, the space field is 0 because the data field contains 0 bytes of data.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

A "wallet" on Solana is an account owned by the System Program, which is one of Solana’s built-in programs. Wallet accounts are primarily used to hold SOL (tracked in the lamports field) and to sign transactions.

When you fetch a wallet account, the response includes the fields shown in the example output.

The data field contains the account's data stored as bytes.

For wallet accounts, this field is empty (0 bytes). Other accounts use this field to store either program state or executable program code.

The executable field indicates if the account's data field contains executable program code.

For wallet and accounts that store program state, this field is false.

The lamports field contains the account's SOL balance, denominated in lamports.

Lamports are the smallest unit of SOL. 1 SOL = 1,000,000,000 lamports.

The owner field shows the program that owns the account.

For wallets, the owner is always the System Program, with the address 11111111111111111111111111111111.

The rentEpoch field is a legacy field from a deprecated mechanism where accounts were charged "rent" (in lamports) to maintain its data on the network.

This field is currently unused, but is included for backwards compatibility.

The space field shows the number of bytes in the data field. This is not a field in the Account type itself, but included in the response.

In this example, the space field is 0 because the data field contains 0 bytes of data.

Example Output
{
"data": {
"type": "Buffer",
"data": []
},
"executable": false,
"lamports": 1000000000,
"owner": "11111111111111111111111111111111",
"rentEpoch": 0,
"space": 0
}

Fetch Token Program

This example fetches the Token Program to demonstrate the difference between wallet and program accounts.

The program account stores the compiled bytecode for the Token Program's source code. You can view this program account on the Solana Explorer.

Fetch Program Account
import { Connection, PublicKey } from "@solana/web3.js";
const connection = new Connection(
"https://api.mainnet-beta.solana.com",
"confirmed"
);
const address = new PublicKey("TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA");
const accountInfo = await connection.getAccountInfo(address);
Console
Click to execute the code.

The Token Program is an executable program account on Solana. Like wallet accounts, programs have the same underlying Account data structure, but with key differences in its fields.

Token Program Account
{
"data": {
"type": "Buffer",
"data": [127, "...truncated, total bytes: 134080...", 0]
},
"executable": true,
"lamports": 4522329612,
"owner": "BPFLoader2111111111111111111111111111111111",
"rentEpoch": 18446744073709552000,
"space": 134080
}

The executable field is set to true, indicating that this account's data field contains executable program code.

Token Program Account
{
"data": {
"type": "Buffer",
"data": [127, "...truncated, total bytes: 134080...", 0]
},
"executable": true,
"lamports": 4522329612,
"owner": "BPFLoader2111111111111111111111111111111111",
"rentEpoch": 18446744073709552000,
"space": 134080
}

For program accounts, the data field stores the program's executable code. In contrast, wallet accounts have an empty data field.

When you deploy a Solana program, the program's executable code is stored in an account's data field.

Token Program Account
{
"data": {
"type": "Buffer",
"data": [127, "...truncated, total bytes: 134080...", 0]
},
"executable": true,
"lamports": 4522329612,
"owner": "BPFLoader2111111111111111111111111111111111",
"rentEpoch": 18446744073709552000,
"space": 134080
}

Executable program accounts also have a program designated as the owner of the of the account.

All program accounts are owned by a Loader program, which is a category of built-in programs that own executable program accounts on Solana.

For the Token Program, the owner is the BPFLoader2 program.

Token Program Account
{
"data": {
"type": "Buffer",
"data": [127, "...truncated, total bytes: 134080...", 0]
},
"executable": true,
"lamports": 4522329612,
"owner": "BPFLoader2111111111111111111111111111111111",
"rentEpoch": 18446744073709552000,
"space": 134080
}

The Token Program is an executable program account on Solana. Like wallet accounts, programs have the same underlying Account data structure, but with key differences in its fields.

The executable field is set to true, indicating that this account's data field contains executable program code.

For program accounts, the data field stores the program's executable code. In contrast, wallet accounts have an empty data field.

When you deploy a Solana program, the program's executable code is stored in an account's data field.

Executable program accounts also have a program designated as the owner of the of the account.

All program accounts are owned by a Loader program, which is a category of built-in programs that own executable program accounts on Solana.

For the Token Program, the owner is the BPFLoader2 program.

Token Program Account
{
"data": {
"type": "Buffer",
"data": [127, "...truncated, total bytes: 134080...", 0]
},
"executable": true,
"lamports": 4522329612,
"owner": "BPFLoader2111111111111111111111111111111111",
"rentEpoch": 18446744073709552000,
"space": 134080
}

Fetch Mint Account

This example fetches the USD Coin (USDC) Mint account to show how programs on Solana store state in separate accounts.

A Mint account is an account owned by the Token Program. It stores global metadata for a specific token, including the total supply, number of decimals, and the accounts authorized to mint or freeze tokens. The Mint account's address uniquely identifies a token on the Solana network.

Fetch Program Account
import { Connection, PublicKey } from "@solana/web3.js";
const connection = new Connection(
"https://api.mainnet-beta.solana.com",
"confirmed"
);
const address = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const accountInfo = await connection.getAccountInfo(address);
Console
Click to execute the code.

The key point to note in this example is that the Mint account stores state, not executable code.

Mint accounts are owned by the Token Program, which includes instructions that define how to create and update Mint accounts.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

The executable field is false because the mint account's data field stores state, not executable code.

The Token Program defines the Mint data type, which is stored in the mint account's data field.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

The data field contains the serialized Mint account state, such as the mint authority, total supply, number of decimals.

To read from a Mint account, you must deserialize the data field into the Mint data type. This is covered in the next step.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

The Token Program (TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA) owns the mint account.

This means that the mint account's data field can only be modified by the instructions defined in the Token Program.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

The key point to note in this example is that the Mint account stores state, not executable code.

Mint accounts are owned by the Token Program, which includes instructions that define how to create and update Mint accounts.

The executable field is false because the mint account's data field stores state, not executable code.

The Token Program defines the Mint data type, which is stored in the mint account's data field.

The data field contains the serialized Mint account state, such as the mint authority, total supply, number of decimals.

To read from a Mint account, you must deserialize the data field into the Mint data type. This is covered in the next step.

The Token Program (TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA) owns the mint account.

This means that the mint account's data field can only be modified by the instructions defined in the Token Program.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

Deserialize Mint Account

The data field of a Solana account contains raw bytes. To interpret this data meaningfully, you must deserialize it into the appropriate data type defined by the program that owns the account.

Most Solana programs provide client libraries with helper functions that abstract away the deserialization process. These functions convert the raw account bytes into structured data types, making it easier to work with the account data.

For example, @solana/spl-token includes the getMint() function to help deserialize a Mint account's data field into the Mint data type.

Deserialize Mint Account Data
import { PublicKey, Connection } from "@solana/web3.js";
import { getMint } from "@solana/spl-token";
const connection = new Connection(
"https://api.mainnet-beta.solana.com",
"confirmed"
);
const address = new PublicKey("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
const mintData = await getMint(connection, address, "confirmed");
Console
Click to execute the code.
Mint Account Type
pub struct Mint {
/// Optional authority used to mint new tokens. The mint authority may only
/// be provided during mint creation. If no mint authority is present
/// then the mint has a fixed supply and no further tokens may be
/// minted.
pub mint_authority: COption<Pubkey>,
/// Total supply of tokens.
pub supply: u64,
/// Number of base 10 digits to the right of the decimal place.
pub decimals: u8,
/// Is `true` if this structure has been initialized
pub is_initialized: bool,
/// Optional authority to freeze token accounts.
pub freeze_authority: COption<Pubkey>,
}

The getMint() function deserializes a mint account's data field into the Mint data type defined by the Token Program.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

You can view the fully deserialized Mint Account data on the Solana Explorer.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The address field contains the Mint account's address.

The mint account's address is used to identify the token on the Solana network.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The mintAuthority field shows the authority allowed to mint new tokens.

This is the only account that can create new units of the token.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The supply field shows the total number of tokens that have been minted.

This value is in the smallest unit of the token. To get the total supply in standard units, adjust the value of the supply field by the decimals.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The decimals field shows the number of decimal places for the token.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The isInitialized field indicates if the Mint account has been initialized. This field is a security check used in the Token Program.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The freezeAuthority field shows the authority allowed to freeze token accounts.

A token account that is frozen cannot transfer or burn the token in the account.

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The tlvData field contains extra data for Token Extensions (requires further deserialization).

This field is only relevant to accounts created by the Token Extension Program (Token2022).

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

The getMint() function deserializes a mint account's data field into the Mint data type defined by the Token Program.

Mint Account
{
"data": {
"type": "Buffer",
"data": [1, "...truncated, total bytes: 82...", 103]
},
"executable": false,
"lamports": 407438077149,
"owner": "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA",
"rentEpoch": 18446744073709552000,
"space": 82
}

You can view the fully deserialized Mint Account data on the Solana Explorer.

The address field contains the Mint account's address.

The mint account's address is used to identify the token on the Solana network.

The mintAuthority field shows the authority allowed to mint new tokens.

This is the only account that can create new units of the token.

The supply field shows the total number of tokens that have been minted.

This value is in the smallest unit of the token. To get the total supply in standard units, adjust the value of the supply field by the decimals.

The decimals field shows the number of decimal places for the token.

The isInitialized field indicates if the Mint account has been initialized. This field is a security check used in the Token Program.

The freezeAuthority field shows the authority allowed to freeze token accounts.

A token account that is frozen cannot transfer or burn the token in the account.

The tlvData field contains extra data for Token Extensions (requires further deserialization).

This field is only relevant to accounts created by the Token Extension Program (Token2022).

Deserialized Mint Data
{
"address": "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
"mintAuthority": "BJE5MMbqXjVwjAF7oxwPYXnTXDyspzZyt4vwenNw5ruG",
"supply": "8985397351591790",
"decimals": 6,
"isInitialized": true,
"freezeAuthority": "7dGbd2QZcCKcTndnHcTL8q7SMVXAkp688NTQYwrRCrar",
"tlvData": {
"type": "Buffer",
"data": []
}
}

Is this page helpful?

सामग्री तालिका

पृष्ठ संपादित करें