Skip to main content
This walkthrough covers sending basic SOL transfers using Para with three different Solana libraries: Solana Web3.js (legacy), Solana Signers v2 (modern), and Coral Anchor (smart contracts). Each approach has different patterns for transaction construction and signing.

Prerequisites

You need an authenticated Para client and basic knowledge of Solana transactions.

Core Dependencies

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
npm install @getpara/react-sdk @getpara/solana-web3-integration @solana/web3.js

Connection Setup

RPC Configuration

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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");

Para Signer Setup

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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);
}

Transaction Construction

Basic SOL Transfer

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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;
};

Balance Validation

Check Sufficient Balance

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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;
};

Sending Transactions

Execute Transfer

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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
  };
};

Complete Implementation Example

Full Transfer Service

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
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;
    }
  }
}

Key Differences

Library Comparison

FeatureSolana Web3.jsSolana Signers v2Coral Anchor
StatusLegacyModern/RecommendedSmart Contracts
Transaction TypeTransactionTransactionMessageTransaction
Instruction CreationSystemProgram.transfer()getTransferSolInstruction()SystemProgram.transfer()
Signingsigner.sendTransaction()signer.modifyAndSignTransactions()provider.sendAndConfirm()
Amount FormatBigInt(lamports)lamports(bigint)BigInt(lamports)
ConfirmationManual pollingStatus checkAutomatic

Transaction Construction Patterns

  • Solana Web3.js
  • Solana Signers v2
  • Coral Anchor
// Legacy approach with Transaction class
const transaction = new Transaction();
transaction.add(SystemProgram.transfer({...}));
transaction.recentBlockhash = blockhash;
transaction.feePayer = publicKey;

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 PublicKey constructor
  • 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

Next Steps

I