Solana's @solana/web3.js SDK is a powerful toolkit for developers building decentralized applications (dApps) on the Solana blockchain. This guide dives into practical Web3.js API examples, covering account management, transaction creation, program interactions, and advanced features like nonce accounts and staking. Whether you're new to Solana or expanding your development skills, this resource will help you master core blockchain operations using JavaScript.
Connecting to the Solana Network
Before performing any operation, establish a connection to the Solana cluster. The most common environment for testing is the devnet, which allows developers to simulate mainnet behavior without real financial risk.
const web3 = require("@solana/web3.js");
let connection = new web3.Connection(web3.clusterApiUrl("devnet"), "confirmed");Once connected, you can retrieve network information such as the current slot, block time, and leader schedule:
let slot = await connection.getSlot();
console.log("Current Slot:", slot);
let blockTime = await connection.getBlockTime(slot);
console.log("Block Time:", blockTime);
let block = await connection.getBlock(slot);
console.log("Block Data:", block);
let slotLeader = await connection.getSlotLeader();
console.log("Slot Leader:", slotLeader);👉 Discover how to interact with live blockchain data using Web3.js tools.
Generating and Managing Key Pairs
Secure key management is essential in blockchain development. The Keypair object enables secure generation, derivation, and restoration of cryptographic keys.
const { Keypair } = require("@solana/web3.js");
// Generate a new key pair
let account = Keypair.generate();
console.log("Public Key:", account.publicKey.toBase58());
console.log("Secret Key:", account.secretKey);You can also recreate a key pair from an existing secret key:
let accountFromSecret = Keypair.fromSecretKey(account.secretKey);
console.log("Reconstructed Public Key:", accountFromSecret.publicKey.toBase58());Additionally, deterministic key pairs can be created from a seed:
let seed = Uint8Array.from([70,60,102,100,...]); // 32-byte array
let accountFromSeed = Keypair.fromSeed(seed);Note: Always store secret keys securely—never expose them in client-side code or public repositories.
Creating and Signing Transactions
Transactions are the primary way to interact with the Solana blockchain. You can create simple transfers or manually construct complex transactions.
Simple Transaction Example
let payer = web3.Keypair.generate();
let toAccount = web3.Keypair.generate();
let transaction = new web3.Transaction().add(
web3.SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: toAccount.publicKey,
lamports: 1000,
})
);
await web3.sendAndConfirmTransaction(connection, transaction, [payer]);Manual Transaction Construction
For more control, build transactions step by step:
let recentBlockhash = await connection.getRecentBlockhash();
let manualTransaction = new web3.Transaction({
recentBlockhash: recentBlockhash.blockhash,
feePayer: payer.publicKey,
});
manualTransaction.add(
web3.SystemProgram.transfer({
fromPubkey: payer.publicKey,
toPubkey: toAccount.publicKey,
lamports: 1000,
})
);
// Sign and verify
let signature = nacl.sign.detached(manualTransaction.serializeMessage(), payer.secretKey);
manualTransaction.addSignature(payer.publicKey, signature);
console.log("Signatures verified:", manualTransaction.verifySignatures());👉 Learn how to build robust transaction workflows with minimal fees.
Working with Program Addresses and Nonce Accounts
Program-derived addresses (PDAs) allow secure interaction between programs without private keys. They are crucial for smart contract development.
const crypto = require("crypto");
let highEntropyBuffer = crypto.randomBytes(31);
let programAddress = await web3.PublicKey.createProgramAddress(
[highEntropyBuffer.slice(0, 31)],
base58publicKey
);Nonce accounts enhance transaction reliability by preventing replay attacks and enabling custodial transaction signing:
let nonceAccount = web3.Keypair.generate();
let minimumAmount = await connection.getMinimumBalanceForRentExemption(web3.NONCE_ACCOUNT_LENGTH);
let createNonceTx = new web3.Transaction().add(
web3.SystemProgram.createNonceAccount({
fromPubkey: payer.publicKey,
noncePubkey: nonceAccount.publicKey,
authorizedPubkey: payer.publicKey,
lamports: minimumAmount,
})
);
await web3.sendAndConfirmTransaction(connection, createNonceTx, [payer, nonceAccount]);After creation, retrieve and validate the nonce account:
let nonceData = await connection.getNonce(nonceAccount.publicKey);
console.log(nonceData);Interacting with Stake and Vote Programs
Solana supports native staking through its Stake Program. Developers can create stake accounts, delegate to validators, and manage lifecycle transitions.
Creating a Stake Account
let stakeAccount = web3.Keypair.generate();
let authorizedAccount = web3.Keypair.generate();
let lamportsForStake = await connection.getMinimumBalanceForRentExemption(web3.StakeProgram.space) + 50;
let createStakeTx = web3.StakeProgram.createAccount({
fromPubkey: fromPublicKey.publicKey,
authorized: new web3.Authorized(authorizedAccount.publicKey, authorizedAccount.publicKey),
lamports: lamportsForStake,
lockup: new web3.Lockup(0, 0, fromPublicKey.publicKey),
stakePubkey: stakeAccount.publicKey,
});Delegating and Managing Stake
After funding the account:
// Check activation status
let stakeState = await connection.getStakeActivation(stakeAccount.publicKey);
console.log("Stake State:", stakeState.state);
// Delegate to a validator
let voteAccounts = await connection.getVoteAccounts();
let votePubkey = new web3.PublicKey(voteAccounts.current[0].votePubkey);
let delegateTx = web3.StakeProgram.delegate({
stakePubkey: stakeAccount.publicKey,
authorizedPubkey: authorizedAccount.publicKey,
votePubkey: votePubkey,
});To withdraw funds, first deactivate the stake:
await web3.sendAndConfirmTransaction(connection, web3.StakeProgram.deactivate({ ... }), [...]);
await web3.sendAndConfirmTransaction(connection, web3.StakeProgram.withdraw({ ... }), [...]);Advanced Data Encoding and Struct Handling
When working with custom programs, structured data encoding becomes essential. Use @solana/web3.js utilities to define and serialize complex types.
Define Custom Structs
import BN from "bn.js";
import { Struct } from "@solana/web3.js";
export class Fee extends Struct {
denominator: BN;
numerator: BN;
}Enum Support
import { Enum } from "@solana/web3.js";
export class AccountType extends Enum {}These patterns ensure compatibility with on-chain program expectations.
Frequently Asked Questions (FAQ)
Q: What is the difference between devnet and mainnet in Solana?
A: Devnet is a public testing environment where tokens have no real value. It’s ideal for development and experimentation. Mainnet-beta is the live network where transactions involve real SOL.
Q: How do I get free SOL for testing?
A: Use the requestAirdrop() method to receive test SOL on devnet. For example: connection.requestAirdrop(publicKey, LAMPORTS_PER_SOL).
Q: Why use nonce accounts instead of regular transactions?
A: Nonce accounts provide better control over transaction timing and prevent replay attacks, especially useful in custodial or batch-processing scenarios.
Q: Can I recover a key pair from a mnemonic phrase?
A: While @solana/web3.js doesn’t support BIP44 mnemonics directly, libraries like bip44-solana can derive key pairs from seed phrases.
Q: How are Ethereum addresses compatible with Solana?
A: Solana supports secp256k1 instructions, allowing Ethereum-style signatures via the Secp256k1 program—ideal for cross-chain identity verification.
Q: What is the purpose of sendAndConfirmRawTransaction?
A: It broadcasts a fully signed serialized transaction directly to the network, useful when handling signing off-device or in secure environments.
Core Keywords: Solana Web3.js, blockchain development, transaction signing, key pair generation, nonce accounts, stake program, program-derived addresses, decentralized applications