Sign Solana transactions using Para’s unified wallet architecture
import 'package:para/para.dart';
// Sign a Solana transaction
final para = Para(apiKey: 'your-api-key');
final wallet = (await para.fetchWallets()).firstWhere((w) => w.type == 'SOLANA');
final transaction = SolanaTransaction(
to: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
lamports: '1000000', // 0.001 SOL
feePayer: null, // Uses wallet as fee payer
recentBlockhash: null, // Fetched automatically with RPC URL
);
final result = await para.signTransaction(
walletId: wallet.id!,
transaction: transaction.toJson(),
chainId: null, // Not needed for Solana
rpcUrl: 'https://api.devnet.solana.com',
);
print('Transaction signed: ${result.signature}');
final transaction = SolanaTransaction(
to: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
lamports: '1000000', // 0.001 SOL
feePayer: null, // Uses wallet as fee payer
recentBlockhash: null, // Fetched automatically with RPC URL
);
final result = await para.signTransaction(
walletId: wallet.id!,
transaction: transaction.toJson(),
chainId: null, // Not needed for Solana
rpcUrl: 'https://api.devnet.solana.com',
);
print('Signed: ${result.signature}');
final balance = await para.getBalance(
walletId: wallet.id!,
token: null, // Native SOL
rpcUrl: 'https://api.devnet.solana.com',
);
// Convert lamports to SOL
final lamports = double.parse(balance);
final sol = lamports / 1000000000;
print('Balance: ${sol.toStringAsFixed(4)} SOL');
final message = 'Hello, Solana!';
final result = await para.signMessage(
walletId: wallet.id!,
message: message,
);
print('Signature: ${result.signature}');
Network | RPC URL | Native Token |
---|---|---|
Devnet | https://api.devnet.solana.com | SOL |
Testnet | https://api.testnet.solana.com | SOL |
Network | RPC URL | Native Token | Network Type |
---|---|---|---|
Mainnet | https://api.mainnet-beta.solana.com | SOL | Production |
Alchemy | https://solana-mainnet.g.alchemy.com/v2/YOUR_KEY | SOL | Production |
import 'package:flutter/material.dart';
import 'package:para/para.dart';
class SolanaWalletView extends StatefulWidget {
final Para para;
final Wallet wallet;
const SolanaWalletView({required this.para, required this.wallet});
@override
State<SolanaWalletView> createState() => _SolanaWalletViewState();
}
class _SolanaWalletViewState extends State<SolanaWalletView> {
bool _isLoading = false;
String? _signature;
final String _rpcUrl = 'https://api.devnet.solana.com';
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
widget.wallet.address ?? 'No address',
style: TextStyle(fontFamily: 'monospace', fontSize: 12),
),
SizedBox(height: 20),
ElevatedButton(
onPressed: _isLoading ? null : _signTransaction,
child: Text(_isLoading ? 'Signing...' : 'Sign Transaction'),
),
if (_signature != null)
Padding(
padding: const EdgeInsets.only(top: 20),
child: Text('Signed: $_signature', style: TextStyle(fontSize: 12)),
),
],
),
);
}
Future<void> _signTransaction() async {
setState(() => _isLoading = true);
try {
final transaction = SolanaTransaction(
to: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
lamports: '1000000', // 0.001 SOL
feePayer: null,
recentBlockhash: null,
);
final result = await widget.para.signTransaction(
walletId: widget.wallet.id!,
transaction: transaction.toJson(),
chainId: null, // Not needed for Solana
rpcUrl: _rpcUrl,
);
setState(() => _signature = result.signature);
} catch (e) {
print('Error: $e');
} finally {
setState(() => _isLoading = false);
}
}
}
// Transaction with memo
final transaction = SolanaTransaction(
to: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
lamports: '1000000',
memo: 'Payment for services',
);
// Transaction with custom blockhash
final transaction = SolanaTransaction(
to: '9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM',
lamports: '1000000',
recentBlockhash: 'custom_blockhash',
feePayer: wallet.address,
);