Documentation Index Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
Use this file to discover all available pages before exploring further.
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
npm install @getpara/react-sdk @getpara/solana-signers-v2-integration @solana/kit @solana/transactions @solana-program/system
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
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" );
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 });
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
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 );
}
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
});
}
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
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 ;
};
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 ;
};
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
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 ;
};
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 ;
};
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
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
};
};
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
};
};
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
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 ;
}
}
}
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 ;
}
}
}
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 TransactionTransactionMessageTransactionInstruction 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
// Legacy approach with Transaction class
const transaction = new Transaction ();
transaction . add ( SystemProgram . transfer ({ ... }));
transaction . recentBlockhash = blockhash ;
transaction . feePayer = publicKey ;
// Modern functional approach with pipes
const transactionMessage = pipe (
createTransactionMessage ({ version: 0 }),
tx => setTransactionMessageFeePayerSigner ( signer , tx ),
tx => setTransactionMessageLifetimeUsingBlockhash ( blockhash , tx ),
tx => appendTransactionMessageInstruction ( instruction , tx )
);
// 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 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
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
SPL Token Transfers Learn to transfer SPL tokens on Solana
Solana Programs Interact with Solana smart contracts
Ethereum Transfers Intermediate · 20 min · Send ETH with Ethers and Viem
Squid Router Integration Advanced · 45 min · Cross-chain USDC bridges
Bulk Wallet Pregeneration Intermediate · 25 min · Large-scale wallet generation