Account Types

Summary

Program accounts hold executable sBPF code. Data accounts store state, owned by programs. System accounts are owned by the System Program. Sysvars provide cluster-wide state accessible at predefined addresses.

The executable field determines an account's category:

This separation of code from mutable state means a program is deployed once and can manage any number of data accounts.

Program accounts

A program account stores executable code. Every program account is owned by a loader program. When a program is deployed, the runtime creates a program account to hold its bytecode.

Diagram of a program account, its 4 components and its loader program.Diagram of a program account, its 4 components and its loader program.

Program data accounts

Programs deployed using loader-v3 (see Loader programs) do not store executable bytecode in their own data field. Instead, their data points to a separate program data account that contains the program code. (See the diagram below.)

A program account with data. The data points to a separate program data accountA program account with data. The data points to a separate program data account

During program deployment or upgrades, buffer accounts are used to temporarily stage the upload.

The following example fetches the Token Program account. The executable field is true, confirming it is a program account.

import { Address, createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc("https://api.mainnet.solana.com");
const programId = "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA" as Address;
const accountInfo = await rpc
.getAccountInfo(programId, { encoding: "base64" })
.send();
console.log(accountInfo);
Console
Click to execute the code.

Data accounts

Data accounts do not contain executable code. They store program-defined state.

Program state account

Programs store their state in data accounts. Creating a program state account involves two steps:

  1. Invoke the System Program to create the account. The System Program transfers ownership to the specified program.
  2. The owning program initializes the account's data field according to its instructions.

Diagram of a data account owned by a program accountDiagram of a data account owned by a program account

The following example creates and fetches a Token Mint account owned by the Token 2022 program.

import {
airdropFactory,
appendTransactionMessageInstructions,
createSolanaRpc,
createSolanaRpcSubscriptions,
createTransactionMessage,
generateKeyPairSigner,
getSignatureFromTransaction,
lamports,
pipe,
sendAndConfirmTransactionFactory,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
signTransactionMessageWithSigners
} from "@solana/kit";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
getInitializeMintInstruction,
getMintSize,
TOKEN_2022_PROGRAM_ADDRESS,
fetchMint
} from "@solana-program/token-2022";
// Create Connection, local validator in this example
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
// Generate keypairs for fee payer
const feePayer = await generateKeyPairSigner();
// Fund fee payer
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: feePayer.address,
lamports: lamports(1_000_000_000n),
commitment: "confirmed"
});
// Generate keypair to use as address of mint
const mint = await generateKeyPairSigner();
// Get default mint account size (in bytes), no extensions enabled
const space = BigInt(getMintSize());
// Get minimum balance for rent exemption
const rent = await rpc.getMinimumBalanceForRentExemption(space).send();
// Instruction to create new account for mint (token 2022 program)
// Invokes the system program
const createAccountInstruction = getCreateAccountInstruction({
payer: feePayer,
newAccount: mint,
lamports: rent,
space,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
});
// Instruction to initialize mint account data
// Invokes the token 2022 program
const initializeMintInstruction = getInitializeMintInstruction({
mint: mint.address,
decimals: 9,
mintAuthority: feePayer.address
});
const instructions = [createAccountInstruction, initializeMintInstruction];
// Get latest blockhash to include in transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
// Create transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }), // Create transaction message
(tx) => setTransactionMessageFeePayerSigner(feePayer, tx), // Set fee payer
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx), // Set transaction blockhash
(tx) => appendTransactionMessageInstructions(instructions, tx) // Append instructions
);
// Sign transaction message with required signers (fee payer and mint keypair)
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
// Send and confirm transaction
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
signedTransaction,
{ commitment: "confirmed" }
);
// Get transaction signature
const transactionSignature = getSignatureFromTransaction(signedTransaction);
console.log("Mint Address:", mint.address);
console.log("Transaction Signature:", transactionSignature);
const accountInfo = await rpc.getAccountInfo(mint.address).send();
console.log(accountInfo);
const mintAccount = await fetchMint(rpc, mint.address);
console.log(mintAccount);
Console
Click to execute the code.

System accounts

Accounts that remain owned by the System Program after creation are called system accounts. Sending SOL to a new address for the first time creates a new account at that address owned by the System Program.

All wallet accounts are system accounts. The fee payer on a transaction must be a system account, because only System Program-owned accounts can pay transaction fees.

A wallet owned by the System Program containing 1,000,000 lamportsA wallet owned by the System Program containing 1,000,000 lamports

The following example generates a new keypair, funds it with SOL, and fetches the account. The owner field is 11111111111111111111111111111111 (the System Program).

import {
airdropFactory,
createSolanaRpc,
createSolanaRpcSubscriptions,
generateKeyPairSigner,
lamports
} from "@solana/kit";
// Create a connection to Solana cluster
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
// Generate a new keypair
const keypair = await generateKeyPairSigner();
console.log(`Public Key: ${keypair.address}`);
// Funding an address with SOL automatically creates an account
const signature = await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: keypair.address,
lamports: lamports(1_000_000_000n),
commitment: "confirmed"
});
const accountInfo = await rpc.getAccountInfo(keypair.address).send();
console.log(accountInfo);
Console
Click to execute the code.

Sysvar accounts

Sysvar accounts are special accounts at predefined addresses that provide read-only access to cluster state data. They update dynamically each slot.

SysvarAddressPurpose
ClockSysvarC1ock11111111111111111111111111111111Current slot, epoch, and Unix timestamp
EpochScheduleSysvarEpochSchedu1e111111111111111111111111Epoch scheduling constants set in genesis
EpochRewardsSysvarEpochRewards1111111111111111111111111Epoch rewards distribution status and progress
RentSysvarRent111111111111111111111111111111111Rental rate and exemption threshold
SlotHashesSysvarS1otHashes111111111111111111111111111Most recent hashes of the slot's parent banks
StakeHistorySysvarStakeHistory1111111111111111111111111Stake activations and deactivations per epoch
LastRestartSlotSysvarLastRestartS1ot1111111111111111111111Last cluster restart slot
InstructionsSysvar1nstructions1111111111111111111111111Serialized instructions of the current transaction
SlotHistorySysvarS1otHistory11111111111111111111111111Record of which slots were produced over the last epoch

The following example fetches and deserializes the Sysvar Clock account.

import { createSolanaRpc } from "@solana/kit";
import { fetchSysvarClock, SYSVAR_CLOCK_ADDRESS } from "@solana/sysvars";
const rpc = createSolanaRpc("https://api.mainnet.solana.com");
const accountInfo = await rpc
.getAccountInfo(SYSVAR_CLOCK_ADDRESS, { encoding: "base64" })
.send();
console.log(accountInfo);
// Automatically fetch and deserialize the account data
const clock = await fetchSysvarClock(rpc);
console.log(clock);
Console
Click to execute the code.

Is this page helpful?

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

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

द्वारा प्रबंधित

© 2026 सोलाना फाउंडेशन। सर्वाधिकार सुरक्षित।
जुड़े रहें
Account Types | Solana