Instructions

Instructions are the fundamental building block for interacting with the Solana blockchain. An instruction is essentially a public function that anyone using the Solana network can call. Each instruction is used to perform a specific action. The execution logic for instructions are stored on programs, where each program defines its own set of instructions. To interact with the Solana network, one or more instructions are added to a transaction and sent to the network to be processed.

SOL transfer example

The diagram below shows how transactions and instructions work together to allow users to interact with the network. In this example, SOL is transferred from one account to another.

The sender account's metadata indicates that it must sign for the transaction. (This allows the System Program to deduct lamports.) Both the sender and recipient accounts must be writable, in order for their lamport balance to change. To execute this instruction, the sender's wallet sends the transaction containing its signature and the message containing the SOL transfer instruction.

SOL transfer diagramSOL transfer diagram

After the transaction is sent, the System Program processes the transfer instruction and updates the lamport balance of both accounts.

SOL transfer process diagramSOL transfer process diagram

The example below shows the code relevant to the above diagrams. (See the System Program's transfer instruction.)

import {
airdropFactory,
appendTransactionMessageInstructions,
createSolanaRpc,
createSolanaRpcSubscriptions,
createTransactionMessage,
generateKeyPairSigner,
getSignatureFromTransaction,
lamports,
pipe,
sendAndConfirmTransactionFactory,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
signTransactionMessageWithSigners
} from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
// Create a connection to cluster
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
// Generate sender and recipient keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
const LAMPORTS_PER_SOL = 1_000_000_000n;
const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL
// Fund sender with airdrop
await airdropFactory({ rpc, rpcSubscriptions })({
recipientAddress: sender.address,
lamports: lamports(LAMPORTS_PER_SOL), // 1 SOL
commitment: "confirmed"
});
// Check balance before transfer
const { value: preBalance1 } = await rpc.getBalance(sender.address).send();
const { value: preBalance2 } = await rpc.getBalance(recipient.address).send();
// Create a transfer instruction for transferring SOL from sender to recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount // 0.01 SOL in lamports
});
// Add the transfer instruction to a new transaction
const { value: latestBlockhash } = await rpc.getLatestBlockhash().send();
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(sender, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([transferInstruction], tx)
);
// Send the transaction to the network
const signedTransaction =
await signTransactionMessageWithSigners(transactionMessage);
await sendAndConfirmTransactionFactory({ rpc, rpcSubscriptions })(
signedTransaction,
{ commitment: "confirmed" }
);
const transactionSignature = getSignatureFromTransaction(signedTransaction);
// Check balance after transfer
const { value: postBalance1 } = await rpc.getBalance(sender.address).send();
const { value: postBalance2 } = await rpc.getBalance(recipient.address).send();
console.log(
"Sender prebalance:",
Number(preBalance1) / Number(LAMPORTS_PER_SOL)
);
console.log(
"Recipient prebalance:",
Number(preBalance2) / Number(LAMPORTS_PER_SOL)
);
console.log(
"Sender postbalance:",
Number(postBalance1) / Number(LAMPORTS_PER_SOL)
);
console.log(
"Recipient postbalance:",
Number(postBalance2) / Number(LAMPORTS_PER_SOL)
);
console.log("Transaction Signature:", transactionSignature);
Console
Click to execute the code.

Instructions

Diagram depicting a transaction with an instruction, broken up into its 3 componentsDiagram depicting a transaction with an instruction, broken up into its 3 components

An Instruction consists of the following information:

  • program_id: The ID of the program being invoked.
  • accounts: An array of account metadata
  • data: A byte array with additional [data] to be used by the instruction.
Instruction struct
pub struct Instruction {
/// Pubkey of the program that executes this instruction.
pub program_id: Pubkey,
/// Metadata describing accounts that should be passed to the program.
pub accounts: Vec<AccountMeta>,
/// Opaque data passed to the program for its own interpretation.
pub data: Vec<u8>,
}

Program ID

The instruction's program_id is the public key address of the program that contains the instruction's business logic.

Account metadata

The instruction's accounts array is an array of AccountMeta structs. Metadata must be provided for each account the instruction interacts with. (This allows transaction to execute instructions in parallel, as long as they do not modify the same account.)

The diagram below depicts a transaction that contains a single instruction. The instruction's accounts array contains metadata for two accounts.

A transaction with one instruction. The instruction contains two AccountMeta structs in its accounts array.A transaction with one instruction. The instruction contains two AccountMeta structs in its accounts array.

The account metadata includes the following information:

  • pubkey: The account's public key address
  • is_signer: Set to true if the account must sign the transaction
  • is_writable: Set to true if the instruction modifies the account's data

To know which accounts an instruction requires, including which must be writable, read-only, or sign the transaction, you must refer to the implementation of the instruction, as defined by the program.

AccountMeta
pub struct AccountMeta {
/// An account's public key.
pub pubkey: Pubkey,
/// True if an `Instruction` requires a `Transaction` signature matching `pubkey`.
pub is_signer: bool,
/// True if the account data or metadata may be mutated during program execution.
pub is_writable: bool,
}

Data

The instruction's data is a byte array that specifies which of the program's instruction to invoke. It also includes any arguments required by the instruction.

Create instruction example

The example below shows the structure of a SOL transfer instruction.

import { generateKeyPairSigner, lamports } from "@solana/kit";
import { getTransferSolInstruction } from "@solana-program/system";
// Generate sender and recipient keypairs
const sender = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
// Define the amount to transfer
const LAMPORTS_PER_SOL = 1_000_000_000n;
const transferAmount = lamports(LAMPORTS_PER_SOL / 100n); // 0.01 SOL
// Create a transfer instruction for transferring SOL from sender to recipient
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount
});
console.log(JSON.stringify(transferInstruction, null, 2));
Console
Click to execute the code.

The code below shows the output from the previous code snippets. The format will differ between SDKs, but notice that each instruction contains the same three pieces of required information: program_id, accounts, data.

{
"accounts": [
{
"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC",
"role": 3,
"signer": {
"address": "Hu28vRMGWpQXN56eaE7jRiDDRRz3vCXEs7EKHRfL6bC",
"keyPair": {
"privateKey": {},
"publicKey": {}
}
}
},
{
"address": "2mBY6CTgeyJNJDzo6d2Umipw2aGUquUA7hLdFttNEj7p",
"role": 1
}
],
"programAddress": "11111111111111111111111111111111",
"data": {
"0": 2,
"1": 0,
"2": 0,
"3": 0,
"4": 128,
"5": 150,
"6": 152,
"7": 0,
"8": 0,
"9": 0,
"10": 0,
"11": 0
}
}

The examples below show how to manually build the transfer instruction. (The Expanded Instruction tab is functionally equivalent to the Instruction tab.)

In practice, you usually don’t have to construct an Instruction manually. Most programs provide client libraries with helper functions that create the instructions for you. If a library isn't available, you can manually build the instruction.

const transferAmount = 0.01; // 0.01 SOL
const transferInstruction = getTransferSolInstruction({
source: sender,
destination: recipient.address,
amount: transferAmount * LAMPORTS_PER_SOL
});

Is this page helpful?

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

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

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

© 2025 सोलाना फाउंडेशन। सर्वाधिकार सुरक्षित।
Instructions | Solana