Prerequisites
You need an authenticated Para client and basic knowledge of Solana transactions.Core Dependencies
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
npm install @getpara/react-sdk @getpara/solana-web3-integration @solana/web3.js
Copy
Ask AI
npm install @getpara/react-sdk @getpara/solana-signers-v2-integration @solana/kit @solana/transactions @solana-program/system
Copy
Ask AI
npm install @getpara/react-sdk @getpara/solana-web3-integration @solana/web3.js @coral-xyz/anchor
Connection Setup
RPC Configuration
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
import { Connection } from "@solana/web3.js";
const DEVNET_RPC_URL = "https://api.devnet.solana.com";
// Create Solana connection
const connection = new Connection(DEVNET_RPC_URL, "confirmed");
Copy
Ask AI
import { createHttpTransport } from "@solana/rpc-spec";
import { createSolanaRpc } from "@solana/kit";
const DEVNET_RPC_URL = "https://api.devnet.solana.com";
// Create HTTP transport
const transport = createHttpTransport({ url: DEVNET_RPC_URL });
// Create Kit RPC client
const kitRpc = createSolanaRpc({ transport });
// Create Para RPC client
const paraRpc = createHttpTransport({ url: DEVNET_RPC_URL });
Copy
Ask AI
import { Connection } from "@solana/web3.js";
import { AnchorProvider } from "@coral-xyz/anchor";
const DEVNET_RPC_URL = "https://api.devnet.solana.com";
// Create Solana connection
const connection = new Connection(DEVNET_RPC_URL, "confirmed");
Para Signer Setup
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
import { ParaSolanaWeb3Signer } from "@getpara/solana-web3-integration";
import { useAccount, useClient } from "@getpara/react-sdk";
// Get Para client and account
const client = useClient();
const { data: account } = useAccount();
// Create Para Solana signer
let signer: ParaSolanaWeb3Signer | null = null;
if (account?.isConnected && connection && client) {
signer = new ParaSolanaWeb3Signer(client, connection);
}
Copy
Ask AI
import { createParaSolanaSigner } from "@getpara/solana-signers-v2-integration";
import { useAccount, useClient } from "@getpara/react-sdk";
// Get Para client and account
const client = useClient();
const { data: account } = useAccount();
// Create Para Solana signer
let signer: any = null;
if (account?.isConnected && paraRpc && client) {
signer = createParaSolanaSigner({
para: client,
rpc: paraRpc
});
}
Copy
Ask AI
import { ParaSolanaWeb3Signer } from "@getpara/solana-web3-integration";
import { AnchorProvider } from "@coral-xyz/anchor";
import { useAccount, useClient } from "@getpara/react-sdk";
// Get Para client and account
const client = useClient();
const { data: account } = useAccount();
// Create Para Solana signer and Anchor provider
let anchorProvider: AnchorProvider | null = null;
if (account?.isConnected && connection && client) {
const signer = new ParaSolanaWeb3Signer(client, connection);
// Create wallet adapter for Anchor
const walletAdapter = {
publicKey: signer.sender,
signTransaction: async (tx: any) => await signer.signTransaction(tx),
signAllTransactions: async (txs: any[]) => await signer.signAllTransactions(txs)
};
anchorProvider = new AnchorProvider(connection, walletAdapter, {
commitment: "confirmed"
});
}
Transaction Construction
Basic SOL Transfer
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
import {
Transaction,
SystemProgram,
PublicKey,
LAMPORTS_PER_SOL
} from "@solana/web3.js";
const constructTransaction = async (
toAddress: string,
solAmount: string,
fromPublicKey: PublicKey
) => {
const toPubKey = new PublicKey(toAddress);
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
// Create transaction
const transaction = new Transaction();
// Add transfer instruction
transaction.add(
SystemProgram.transfer({
fromPubkey: fromPublicKey,
toPubkey: toPubKey,
lamports: BigInt(amountLamports)
})
);
// Set transaction parameters
const { blockhash } = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = fromPublicKey;
return transaction;
};
Copy
Ask AI
import { pipe } from "@solana/transactions";
import {
getTransferSolInstruction,
lamports,
address
} from "@solana-program/system";
import {
appendTransactionMessageInstruction,
createTransactionMessage,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash
} from "@solana/transactions";
const constructTransaction = async (
toAddress: string,
solAmount: string,
signerAddress: any
) => {
// Get latest blockhash
const { value: latestBlockhash } = await kitRpc.getLatestBlockhash().send();
// Convert SOL to lamports
const amountLamports = BigInt(parseFloat(solAmount) * 1e9);
// Create transfer instruction
const transferInstruction = getTransferSolInstruction({
source: signerAddress,
destination: address(toAddress),
amount: lamports(amountLamports)
});
// Build transaction message
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayerSigner(signerAddress, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash.blockhash, tx),
tx => appendTransactionMessageInstruction(transferInstruction, tx)
);
return transactionMessage;
};
Copy
Ask AI
import {
Transaction,
SystemProgram,
PublicKey,
LAMPORTS_PER_SOL
} from "@solana/web3.js";
const constructTransaction = async (
toAddress: string,
solAmount: string,
walletPublicKey: PublicKey
) => {
const toPubKey = new PublicKey(toAddress);
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
// Create transaction
const transaction = new Transaction();
// Add transfer instruction
transaction.add(
SystemProgram.transfer({
fromPubkey: walletPublicKey,
toPubkey: toPubKey,
lamports: BigInt(amountLamports)
})
);
// Set transaction parameters
const { blockhash } = await connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = walletPublicKey;
return transaction;
};
Balance Validation
Check Sufficient Balance
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
const validateTransaction = async (
userPublicKey: PublicKey,
solAmount: string
) => {
// Get current balance
const balanceLamports = await connection.getBalance(userPublicKey);
// Calculate amount in lamports
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
// Estimate transaction fee (5000 lamports is typical)
const estimatedFee = 5000;
const totalCost = amountLamports + estimatedFee;
if (totalCost > balanceLamports) {
throw new Error(
`Insufficient balance. Need ${totalCost / LAMPORTS_PER_SOL} SOL, have ${balanceLamports / LAMPORTS_PER_SOL} SOL`
);
}
return true;
};
Copy
Ask AI
const validateTransaction = async (
signerAddress: any,
solAmount: string
) => {
// Get current balance
const { value: balance } = await kitRpc.getBalance(signerAddress).send();
// Calculate amount in lamports
const amountLamports = BigInt(parseFloat(solAmount) * 1e9);
// Estimate transaction fee
const estimatedFee = BigInt(5000);
const totalCost = amountLamports + estimatedFee;
if (totalCost > balance) {
throw new Error(
`Insufficient balance. Need ${Number(totalCost) / 1e9} SOL, have ${Number(balance) / 1e9} SOL`
);
}
return true;
};
Copy
Ask AI
const validateTransaction = async (
walletPublicKey: PublicKey,
solAmount: string
) => {
// Get current balance
const balanceLamports = await connection.getBalance(walletPublicKey);
// Calculate amount in lamports
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
// Estimate transaction fee
const estimatedFee = 5000;
const totalCost = amountLamports + estimatedFee;
if (totalCost > balanceLamports) {
throw new Error(
`Insufficient balance. Need ${totalCost / LAMPORTS_PER_SOL} SOL, have ${balanceLamports / LAMPORTS_PER_SOL} SOL`
);
}
return true;
};
Sending Transactions
Execute Transfer
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
const sendSolTransfer = async (
toAddress: string,
solAmount: string,
fromPublicKey: PublicKey
) => {
// Validate transaction
await validateTransaction(fromPublicKey, solAmount);
// Construct transaction
const transaction = await constructTransaction(toAddress, solAmount, fromPublicKey);
// Send transaction using Para signer
const txSignature = await signer.sendTransaction(transaction);
console.log("Transaction sent:", txSignature);
// Wait for confirmation with polling
let receipt = null;
while (!receipt) {
receipt = await connection.getSignatureStatus(txSignature, {
searchTransactionHistory: true
});
if (receipt?.value?.confirmationStatus === "confirmed" ||
receipt?.value?.confirmationStatus === "finalized") {
break;
}
// Wait 500ms before next check
await new Promise(resolve => setTimeout(resolve, 500));
}
console.log("Transaction confirmed:", receipt);
return {
signature: txSignature,
status: receipt?.value?.confirmationStatus,
slot: receipt?.value?.slot
};
};
Copy
Ask AI
import {
compileTransaction,
getBase64EncodedWireTransaction
} from "@solana/transactions";
const sendSolTransfer = async (
toAddress: string,
solAmount: string,
signerAddress: any
) => {
// Validate transaction
await validateTransaction(signerAddress, solAmount);
// Construct transaction message
const transactionMessage = await constructTransaction(toAddress, solAmount, signerAddress);
// Sign transaction
const [signedTransaction] = await signer.modifyAndSignTransactions([
compileTransaction(transactionMessage)
]);
// Serialize transaction
const serializedTransaction = getBase64EncodedWireTransaction(signedTransaction);
// Send transaction
const { value: signature } = await kitRpc.sendTransaction(
serializedTransaction,
{
encoding: "base64",
skipPreflight: false,
preflightCommitment: "confirmed"
}
).send();
console.log("Transaction sent:", signature);
// Wait for confirmation
const { value: statuses } = await kitRpc.getSignatureStatuses([signature]).send();
const status = statuses[0];
console.log("Transaction confirmed:", status);
return {
signature,
status: status?.confirmationStatus,
slot: status?.slot
};
};
Copy
Ask AI
const sendSolTransfer = async (
toAddress: string,
solAmount: string,
walletPublicKey: PublicKey
) => {
// Validate transaction
await validateTransaction(walletPublicKey, solAmount);
// Construct transaction
const transaction = await constructTransaction(toAddress, solAmount, walletPublicKey);
// Send and confirm transaction using Anchor provider
const txSignature = await anchorProvider.sendAndConfirm(transaction);
console.log("Transaction sent and confirmed:", txSignature);
return {
signature: txSignature,
status: "confirmed"
};
};
Complete Implementation Example
Full Transfer Service
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
import {
Connection,
Transaction,
SystemProgram,
PublicKey,
LAMPORTS_PER_SOL
} from "@solana/web3.js";
import { ParaSolanaWeb3Signer } from "@getpara/solana-web3-integration";
class SolanaWeb3TransferService {
private connection: Connection;
private signer: ParaSolanaWeb3Signer;
constructor(rpcUrl: string, paraClient: any) {
this.connection = new Connection(rpcUrl, "confirmed");
this.signer = new ParaSolanaWeb3Signer(paraClient, this.connection);
}
async transfer(toAddress: string, solAmount: string) {
try {
const fromPublicKey = this.signer.sender;
// Validate balance
const balanceLamports = await this.connection.getBalance(fromPublicKey);
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
const estimatedFee = 5000;
if (balanceLamports < amountLamports + estimatedFee) {
throw new Error("Insufficient balance");
}
// Create transaction
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: fromPublicKey,
toPubkey: new PublicKey(toAddress),
lamports: BigInt(amountLamports)
})
);
const { blockhash } = await this.connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = fromPublicKey;
// Send transaction
const signature = await this.signer.sendTransaction(transaction);
// Wait for confirmation
await this.connection.confirmTransaction(signature);
return { success: true, signature };
} catch (error) {
console.error("Transfer failed:", error);
throw error;
}
}
}
Copy
Ask AI
import { pipe } from "@solana/transactions";
import { createSolanaRpc, createHttpTransport } from "@solana/kit";
import { getTransferSolInstruction, lamports, address } from "@solana-program/system";
import { createParaSolanaSigner } from "@getpara/solana-signers-v2-integration";
class SolanaSignersTransferService {
private kitRpc: any;
private signer: any;
constructor(rpcUrl: string, paraClient: any) {
const transport = createHttpTransport({ url: rpcUrl });
this.kitRpc = createSolanaRpc({ transport });
this.signer = createParaSolanaSigner({
para: paraClient,
rpc: createHttpTransport({ url: rpcUrl })
});
}
async transfer(toAddress: string, solAmount: string) {
try {
const signerAddress = this.signer.address;
// Validate balance
const { value: balance } = await this.kitRpc.getBalance(signerAddress).send();
const amountLamports = BigInt(parseFloat(solAmount) * 1e9);
const estimatedFee = BigInt(5000);
if (balance < amountLamports + estimatedFee) {
throw new Error("Insufficient balance");
}
// Get latest blockhash
const { value: latestBlockhash } = await this.kitRpc.getLatestBlockhash().send();
// Create transfer instruction
const transferInstruction = getTransferSolInstruction({
source: signerAddress,
destination: address(toAddress),
amount: lamports(amountLamports)
});
// Build and sign transaction
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayerSigner(signerAddress, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash.blockhash, tx),
tx => appendTransactionMessageInstruction(transferInstruction, tx)
);
const [signedTransaction] = await this.signer.modifyAndSignTransactions([
compileTransaction(transactionMessage)
]);
// Send transaction
const serialized = getBase64EncodedWireTransaction(signedTransaction);
const { value: signature } = await this.kitRpc.sendTransaction(serialized).send();
return { success: true, signature };
} catch (error) {
console.error("Transfer failed:", error);
throw error;
}
}
}
Copy
Ask AI
import {
Connection,
Transaction,
SystemProgram,
PublicKey,
LAMPORTS_PER_SOL
} from "@solana/web3.js";
import { AnchorProvider } from "@coral-xyz/anchor";
import { ParaSolanaWeb3Signer } from "@getpara/solana-web3-integration";
class AnchorTransferService {
private connection: Connection;
private anchorProvider: AnchorProvider;
constructor(rpcUrl: string, paraClient: any) {
this.connection = new Connection(rpcUrl, "confirmed");
const signer = new ParaSolanaWeb3Signer(paraClient, this.connection);
const walletAdapter = {
publicKey: signer.sender,
signTransaction: async (tx: any) => await signer.signTransaction(tx),
signAllTransactions: async (txs: any[]) => await signer.signAllTransactions(txs)
};
this.anchorProvider = new AnchorProvider(this.connection, walletAdapter, {
commitment: "confirmed"
});
}
async transfer(toAddress: string, solAmount: string) {
try {
const fromPublicKey = this.anchorProvider.wallet.publicKey;
// Validate balance
const balanceLamports = await this.connection.getBalance(fromPublicKey);
const amountLamports = parseFloat(solAmount) * LAMPORTS_PER_SOL;
const estimatedFee = 5000;
if (balanceLamports < amountLamports + estimatedFee) {
throw new Error("Insufficient balance");
}
// Create transaction
const transaction = new Transaction().add(
SystemProgram.transfer({
fromPubkey: fromPublicKey,
toPubkey: new PublicKey(toAddress),
lamports: BigInt(amountLamports)
})
);
const { blockhash } = await this.connection.getLatestBlockhash();
transaction.recentBlockhash = blockhash;
transaction.feePayer = fromPublicKey;
// Send and confirm transaction
const signature = await this.anchorProvider.sendAndConfirm(transaction);
return { success: true, signature };
} catch (error) {
console.error("Transfer failed:", error);
throw error;
}
}
}
Key Differences
Library Comparison
| Feature | Solana Web3.js | Solana Signers v2 | Coral Anchor |
|---|---|---|---|
| Status | Legacy | Modern/Recommended | Smart Contracts |
| Transaction Type | Transaction | TransactionMessage | Transaction |
| Instruction Creation | SystemProgram.transfer() | getTransferSolInstruction() | SystemProgram.transfer() |
| Signing | signer.sendTransaction() | signer.modifyAndSignTransactions() | provider.sendAndConfirm() |
| Amount Format | BigInt(lamports) | lamports(bigint) | BigInt(lamports) |
| Confirmation | Manual polling | Status check | Automatic |
Transaction Construction Patterns
- Solana Web3.js
- Solana Signers v2
- Coral Anchor
Copy
Ask AI
// Legacy approach with Transaction class
const transaction = new Transaction();
transaction.add(SystemProgram.transfer({...}));
transaction.recentBlockhash = blockhash;
transaction.feePayer = publicKey;
Copy
Ask AI
// Modern functional approach with pipes
const transactionMessage = pipe(
createTransactionMessage({ version: 0 }),
tx => setTransactionMessageFeePayerSigner(signer, tx),
tx => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
tx => appendTransactionMessageInstruction(instruction, tx)
);
Copy
Ask AI
// Anchor provider abstraction
const transaction = new Transaction();
transaction.add(SystemProgram.transfer({...}));
// Provider handles blockhash and fee payer automatically
const signature = await provider.sendAndConfirm(transaction);
Best Practices
Library Selection
- Solana Web3.js: Use for compatibility with existing projects, but consider migrating
- Solana Signers v2: Recommended for new projects, modern patterns, better performance
- Coral Anchor: Best for dApps interacting with Anchor-based smart contracts
Transaction Safety
- Always validate recipient addresses using
PublicKeyconstructor - Check balance including fees before transaction construction
- Use appropriate commitment levels (“confirmed” for most cases)
- Handle network errors gracefully with proper retry logic
- Monitor transaction confirmation rather than assuming success
Performance Optimization
- Reuse connection instances rather than creating new ones
- Batch multiple transfers when possible
- Use appropriate RPC endpoints for your use case
- Monitor transaction fees and adjust as needed