Sending transactions is a fundamental skill for any blockchain developer. If you're building on Solana, knowing how to programmatically send transactions using the solana-web3.js library is essential. This guide provides a clear, step-by-step approach to sending a Solana transaction quickly and effectively.
Prerequisites and Installation
Before you start, ensure you have Node.js and npm installed on your system. You will then need to install the necessary JavaScript libraries.
Install the Solana Web3.js Library
The primary library for interacting with the Solana blockchain is @solana/web3.js. Install it using npm with the following command:
npm install @solana/web3.jsInstall the Base58 Encoding Library
Many Solana tools and wallets represent private keys as Base58-encoded strings. To decode these into a format the library can use, install the bs58 package:
npm install bs58Setting Up Your Development Environment
With the libraries installed, you can begin writing the code to construct and send a transaction.
Import Required Modules
Start by importing the installed modules into your JavaScript file (e.g., index.js).
const web3 = require("@solana/web3.js");
const bs58 = require("bs58");Establishing a Connection to the Solana Network
To interact with the blockchain, your application needs to connect to a Solana node. This connection allows you to query data and submit transactions.
Create a Connection Instance
You need a reliable RPC endpoint to connect to the network. Initialize a connection object by providing your endpoint URL.
const connection = new web3.Connection("YOUR_RPC_ENDPOINT_HERE");👉 Get a reliable Solana RPC endpoint
A stable connection is crucial for successful transaction broadcasting and confirmation.
Preparing the Transaction Accounts
A transaction requires a sender and a recipient. The sender's account must be derived from their private key, which authorizes the transaction.
Handling the Private Key Securely
It is critical to handle private keys with care. Never hardcode them into your source files. Instead, use environment variables.
The following code decodes a Base58-encoded private key string into a Uint8Array, which is the format required by solana-web3.js:
// Assuming your private key is stored in an environment variable named PRIVATE_KEY
const privateKey = new Uint8Array(bs58.decode(process.env['PRIVATE_KEY']));Deriving the Keypair from the Private Key
Once decoded, you can create a Keypair object, which represents the sender's account and is used to sign transactions.
const senderAccount = web3.Keypair.fromSecretKey(privateKey);Generating a Recipient Address
For this tutorial, we will generate a new keypair to act as the recipient. In a real application, this would be a specific user's public key.
const recipientAccount = web3.Keypair.generate();
const recipientPublicKey = recipientAccount.publicKey;Constructing and Sending the Transaction
The core logic involves building the transaction object and sending it to the network.
Building the Transaction
A transaction is built by adding instructions. Here, we add a transfer instruction from the SystemProgram, which handles native SOL token transfers.
(async () => {
const transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: senderAccount.publicKey,
toPubkey: recipientPublicKey,
lamports: web3.LAMPORTS_PER_SOL * 0.001, // Sending 0.001 SOL
}),
);Sending and Confirming the Transaction
The sendAndConfirmTransaction method is used to both send the transaction and wait for its confirmation on the blockchain. This ensures the transaction was successful.
const signature = await web3.sendAndConfirmTransaction(
connection,
transaction,
[senderAccount], // The signer(s) of the transaction
);
console.log('Transaction confirmed with signature:', signature);
})();This function returns a transaction signature, which is a unique hash you can use to look up the transaction on a Solana block explorer.
Summary of the Process
To quickly recap, sending a transaction involves these key steps:
- Import the necessary libraries:
@solana/web3.jsandbs58. - Establish a connection: Link your application to the Solana network via an RPC endpoint.
- Set up accounts: Securely decode the sender's private key and identify the recipient's public key.
- Build the transaction: Create a transaction object and add the transfer instruction.
- Send and confirm: Broadcast the transaction to the network and await its confirmation.
After running your code, you can verify the transaction was successful by checking the sender's wallet or using a block explorer with the returned transaction signature.
Frequently Asked Questions
What are lamports in Solana?
A lamport is the smallest fractional unit of the SOL token on the Solana blockchain, named in honor of Leslie Lamport, a computer scientist. One SOL is equivalent to 1,000,000,000 (1 billion) lamports. All transactions and account balances on-chain are ultimately calculated in lamports.
Why do I need to decode my private key?
Wallets often export private keys as Base58-encoded strings for ease of use and readability. The solana-web3.js library requires the key in a raw binary format (Uint8Array) to create a signer object. The bs58.decode() function performs this conversion from the string representation.
What is an RPC endpoint and why do I need one?
An RPC (Remote Procedure Call) endpoint is a URL provided by a node on the Solana network. Your application uses this endpoint to communicate with the blockchain—to read data, check balances, and submit transactions. A reliable, high-performance endpoint is vital for ensuring your application runs smoothly.
👉 Explore high-performance node providers
Can I send SPL tokens instead of SOL with this method?
No, this tutorial specifically covers sending native SOL tokens via the SystemProgram.transfer instruction. Sending SPL tokens (like USDC or other custom tokens) requires interacting with the SPL Token Program using a different set of instructions, such as creating a token transfer instruction.
What does transaction confirmation mean?
Confirmation means that the network has reached consensus that your transaction is valid and has been included in a block. The sendAndConfirmTransaction function waits for this process to complete, providing assurance that the transaction was successful and is now part of the immutable blockchain history.
My transaction failed. What should I check?
First, check the error message in your console. Common reasons for failure include:
- Insufficient balance: The sender account must have enough SOL to cover the transfer amount and the transaction fee.
- Invalid private key: Ensure the private key was decoded correctly and matches the intended sender account.
- Connection issues: Verify that your RPC endpoint is online and responsive.