Introduction
This guide demonstrates how to integrate Para with Solana in your Flutter applications. Para acts as a secure signer for your Solana transactions, while the Solana Dart package handles the blockchain interactions.
Para’s approach to Solana transaction signing is designed for flexibility and security:
- Para signs the raw transaction bytes without modifying the transaction data
- Your application maintains full control over transaction construction
- Your private keys remain secure in Para’s wallet infrastructure
Prerequisites
Before you begin, ensure you have:
- Para SDK set up in your Flutter project (see the Setup Guide)
- A user authenticated with Para
- Solana Dart package installed in your project
Setting Up the Para Solana Signer
The Para SDK provides a Solana signer that works with the Solana Dart package. First, let’s create the necessary components:
import 'package:para/para.dart';
import 'package:solana/solana.dart' as web3;
// Initialize Para and get wallet (assuming user is already authenticated)
final para = Para(
environment: Environment.beta,
apiKey: 'YOUR_API_KEY',
);
// Set up Solana client with the desired network
final devnetRpcUrl = Uri.parse('https://api.devnet.solana.com');
final devnetWsUrl = Uri.parse('wss://api.devnet.solana.com');
final solanaClient = web3.SolanaClient(
rpcUrl: devnetRpcUrl,
websocketUrl: devnetWsUrl,
);
// Initialize Para Solana signer
final solanaSigner = ParaSolanaWeb3Signer(
para: para,
solanaClient: solanaClient,
);
Sending Transactions
After signing a transaction, you can send it to the Solana network:
Future<String> sendSolanaTransaction(
Wallet wallet,
String recipientAddress,
double amountInSol,
) async {
// Convert wallet address to Solana public key
final publicKey = web3.Ed25519HDPublicKey.fromBase58(wallet.address!);
// Convert recipient address to Solana public key
final recipient = web3.Ed25519HDPublicKey.fromBase58(recipientAddress);
// Get the latest blockhash (required for Solana transactions)
final blockhash = (await solanaClient.rpcClient.getLatestBlockhash()).value;
// Convert SOL amount to lamports (Solana's smallest unit)
final lamports = (web3.lamportsPerSol * amountInSol).toInt();
// Create a transfer instruction
final instruction = web3.SystemInstruction.transfer(
fundingAccount: publicKey,
recipientAccount: recipient,
lamports: lamports,
);
// Create and compile the message
final message = web3.Message(instructions: [instruction]);
final compiledMessage = message.compile(
recentBlockhash: blockhash.blockhash,
feePayer: publicKey,
);
// Sign the transaction using Para
final signedTransaction = await solanaSigner.signTransaction(compiledMessage);
// Send the signed transaction to the network
final signature = await solanaSigner.sendTransaction(signedTransaction);
return signature;
}
Checking Transaction Status
After sending a transaction, you may want to check its status:
Future<bool> confirmTransaction(String signature) async {
try {
final confirmation = await solanaClient.rpcClient
.confirmTransaction(signature, commitment: web3.Commitment.confirmed);
return confirmation.value;
} catch (e) {
return false;
}
}
Working with SPL Tokens
Para can also sign transactions involving SPL tokens (Solana’s token standard). Here’s an example of transferring an SPL token:
import 'package:solana/solana.dart' as web3;
import 'package:solana/token_program.dart' as token_program;
Future<String> transferSplToken(
Wallet wallet,
String recipientAddress,
String tokenMintAddress,
double amount,
int decimals,
) async {
// Convert wallet address to Solana public key
final publicKey = web3.Ed25519HDPublicKey.fromBase58(wallet.address!);
// Convert recipient address to Solana public key
final recipient = web3.Ed25519HDPublicKey.fromBase58(recipientAddress);
// Convert token mint address to Solana public key
final tokenMint = web3.Ed25519HDPublicKey.fromBase58(tokenMintAddress);
// Get the latest blockhash
final blockhash = (await solanaClient.rpcClient.getLatestBlockhash()).value;
// Find the token account addresses for sender and recipient
final senderTokenAccount = await token_program.findAssociatedTokenAddress(
owner: publicKey,
mint: tokenMint,
);
final recipientTokenAccount = await token_program.findAssociatedTokenAddress(
owner: recipient,
mint: tokenMint,
);
// Check if recipient token account exists, if not create it
final instructions = <web3.Instruction>[];
final accounts = await solanaClient.rpcClient
.getTokenAccountsByOwner(
recipient.toBase58(),
const web3.TokenAccountsFilter.byMint(tokenMint),
);
final recipientTokenAccountExists = accounts.value.any(
(account) => account.pubkey == recipientTokenAccount,
);
if (!recipientTokenAccountExists) {
instructions.add(
token_program.createAssociatedTokenAccountInstruction(
associatedToken: recipientTokenAccount,
payer: publicKey,
owner: recipient,
mint: tokenMint,
),
);
}
// Convert token amount accounting for decimals
final tokenAmount = (amount * (10 * decimals)).toInt();
// Add token transfer instruction
instructions.add(
token_program.transferInstruction(
source: senderTokenAccount,
destination: recipientTokenAccount,
owner: publicKey,
amount: tokenAmount,
),
);
// Create and compile the message
final message = web3.Message(instructions: instructions);
final compiledMessage = message.compile(
recentBlockhash: blockhash.blockhash,
feePayer: publicKey,
);
// Sign the transaction using Para
final signedTransaction = await solanaSigner.signTransaction(compiledMessage);
// Send the signed transaction
final signature = await solanaSigner.sendTransaction(signedTransaction);
return signature;
}
Best Practices
When using Para with Solana:
- Always verify transaction data before signing: Para signs whatever you provide, so ensure transaction data is correct
- Use appropriate commitment levels: For important transactions, wait for “confirmed” or “finalized” commitment
- Handle network congestion: Solana transactions can fail during network congestion, implement appropriate retry mechanisms
- Check token accounts: Always verify token accounts exist before sending SPL tokens
- Test on devnet first: Always test your integration on Solana devnet before moving to mainnet
Example
For an example of signing with Solana transactions using para and the Solana Dart package, check out the following code example:
Resources
For more information about using the Solana Dart package, refer to the official documentation: