Creating transactions is a foundational skill for any developer building on the Solana blockchain. Whether you're transferring tokens, interacting with decentralized applications, or deploying smart contracts, everything revolves around transactions. In this guide, we'll walk through how transactions work on Solana, their structure, and how to create and send them using the @solana/web3.js library.
How Transactions Work on Solana
All changes to on-chain data on Solana occur through transactions. These are atomic operations that either fully succeed or completely fail—there’s no in-between. This ensures data consistency across the network.
👉 Discover how blockchain transactions power decentralized applications today.
Transactions Are Atomic
Atomicity means that a transaction is treated as a single, indivisible unit. If any part of the transaction fails—like insufficient funds or an invalid signature—the entire operation rolls back as if it never happened.
Imagine buying coffee online:
- Your account is debited.
- The merchant receives payment.
Both steps must complete successfully. If one fails, neither should take effect. Solana enforces this behavior so developers don’t have to manually manage rollback logic.
This model prevents partial executions and maintains trustless integrity in decentralized environments.
Structure of a Solana Transaction
Each transaction contains one or more instructions, which tell Solana programs what actions to perform.
What’s Inside an Instruction?
Every instruction includes:
- Accounts involved: A list of public keys for accounts that will be read from or written to.
- Program to invoke: The public key of the on-chain program (smart contract) that processes the instruction.
- Instruction data: A byte array containing parameters for the program.
Solana’s high throughput comes from its ability to process non-overlapping transactions in parallel. If two transactions modify different sets of accounts, they can be executed simultaneously.
For example, when sending SOL between wallets, you use the built-in System Program via SystemProgram.transfer():
const transaction = new Transaction();
const sendSolInstruction = SystemProgram.transfer({
fromPubkey: sender,
toPubkey: recipient,
lamports: LAMPORTS_PER_SOL * amount,
});
transaction.add(sendSolInstruction);Here:
fromPubkeyandtoPubkeyidentify sender and receiver.lamportsare the smallest unit of SOL (1 SOL = 1,000,000,000 lamports).
Once added to a transaction, it must be signed and submitted to the network.
Sending and Confirming Transactions
To broadcast a transaction, use sendAndConfirmTransaction():
const signature = await sendAndConfirmTransaction(
connection,
transaction,
[senderKeypair]
);This function requires:
- A connection to a Solana cluster (e.g., Devnet).
- The transaction object.
- An array of signers—the first signer pays the fee.
Only the sender’s keypair is needed here since they’re initiating and funding the transfer.
Understanding Transaction Fees
Transaction fees on Solana are:
- Deterministic: You know the cost before submission.
- Paid by the first signer: The primary signer must have enough SOL to cover fees.
If the sender has no balance, you’ll see an error like:
"Transaction simulation failed: Attempt to debit an account but found no record of a prior credit."
To avoid this during development, request test SOL using an airdrop:
await airdropIfRequired(
connection,
keypair.publicKey,
1 * LAMPORTS_PER_SOL,
0.5 * LAMPORTS_PER_SOL
);Alternatively, use the CLI:
solana airdrop 1 --url https://api.devnet.solana.comThese tools are essential for testing on Devnet, where SOL has no real-world value.
👉 Learn how to test blockchain interactions safely with developer tools.
Viewing Transactions on Solana Explorer
All transactions are public and can be viewed on Solana Explorer. After sending a transaction, copy the returned signature and search for it on the explorer.
You’ll see details like:
- Timestamp and block number
- Status (success/failure)
- Fee amount
- List of instructions and accounts involved
Make sure to set the network to Devnet when viewing test transactions.
This transparency enhances trust and enables debugging in real time.
Hands-On Lab: Send SOL Programmatically
Let’s build a simple script to send SOL between accounts.
Step 1: Set Up Project Scaffolding
Ensure you have Node.js and dotenv installed. Use the same environment setup from previous lessons.
Create transfer.ts:
import {
Connection,
Transaction,
SystemProgram,
sendAndConfirmTransaction,
PublicKey,
} from "@solana/web3.js";
import "dotenv/config";
import { getKeypairFromEnvironment } from "@solana-developers/helpers";
const suppliedToPubkey = process.argv[2] || null;
if (!suppliedToPubkey) {
console.log("Please provide a public key to send to");
process.exit(1);
}
const senderKeypair = getKeypairFromEnvironment("SECRET_KEY");
const toPubkey = new PublicKey(suppliedToPubkey);
const connection = new Connection("https://api.devnet.solana.com", "confirmed");
console.log("✅ Loaded keypair, destination, and connected to Devnet");Run with:
npx esrun transfer.ts <recipient-wallet-address>Step 2: Add Transfer Logic
Append this code:
const transaction = new Transaction();
const LAMPORTS_TO_SEND = 5000; // ~$0.0005 at current rates
const sendSolInstruction = SystemProgram.transfer({
fromPubkey: senderKeypair.publicKey,
toPubkey,
lamports: LAMPORTS_TO_SEND,
});
transaction.add(sendSolInstruction);
const signature = await sendAndConfirmTransaction(connection, transaction, [
senderKeypair,
]);
console.log(`💸 Sent ${LAMPORTS_TO_SEND} lamports to ${toPubkey}`);
console.log(`Transaction signature: ${signature}`);This sends a small amount of test SOL. Adjust LAMPORTS_TO_SEND as needed.
Frequently Asked Questions (FAQ)
What is a Lamport?
A lamport is the smallest unit of SOL, equivalent to 0.000000001 SOL. It's named after computer scientist Leslie Lamport.
Why do I need test SOL?
Test SOL allows developers to simulate real transactions without spending real money. It's available only on Devnet and Localnet.
How fast are Solana transactions?
Solana achieves finality in about 2–4 seconds, making it ideal for high-frequency applications like DeFi and gaming.
Can a transaction partially succeed?
No. Solana transactions are atomic—either all instructions succeed or none do.
How do I check if my transaction succeeded?
Use the transaction signature with Solana Explorer or query it programmatically:
await connection.getTransaction(signature);What does “confirmed” mean in connection settings?
"Confirmed" refers to confirmation level, meaning the node waits for votes from validators before returning a result. Other levels include "finalized" (strongest) and "processed" (fastest but least secure).
Core Keywords
- Solana transactions
- Send SOL programmatically
- Web3.js tutorial
- Blockchain development
- Transaction fees on Solana
- Atomic transactions
- Devnet airdrop
- Solana Explorer
With this foundation, you're ready to explore more complex interactions—like calling custom programs or building dApps. Practice creating and monitoring transactions until the flow becomes second nature.
👉 Start experimenting with real blockchain tools and explore advanced features now.