Skip to main content

Overview

The Solana connection allows you to interact with the Solana blockchain, query data, and prepare transactions using the Flutter Solana package.

Prerequisites

  • Dynamic SDK initialized (see Quickstart)
  • User authenticated (see Authentication)
  • Solana wallets enabled in your Dynamic dashboard
  • dynamic_sdk_solana package installed

Create Connection

import 'package:dynamic_sdk/dynamic_sdk.dart';

final sdk = DynamicSDK.instance;

void createConnection() {
  final connection = sdk.solana.createConnection();
  print('Solana connection created');
}

Get Latest Blockhash

Required for building transactions:
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:solana/solana.dart';

final sdk = DynamicSDK.instance;

Future<String> getBlockhash() async {
  final connection = sdk.solana.createConnection();
  final result = await connection.getLatestBlockhash();
  print('Latest blockhash: ${result.blockhash}');
  return result.blockhash;
}

Query Account Balance

import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:solana/solana.dart';

final sdk = DynamicSDK.instance;

Future<int> getBalance(String address) async {
  try {
    final connection = sdk.solana.createConnection();
    final pubkey = Pubkey.fromString(address);
    final balance = await connection.getBalance(pubkey);
    return balance;
  } catch (e) {
    print('Failed to get balance: $e');
    rethrow;
  }
}

Get Solana Wallets

import 'package:dynamic_sdk/dynamic_sdk.dart';

final sdk = DynamicSDK.instance;

List<BaseWallet> getSolanaWallets() {
  final solanaWallets = sdk.wallets.userWallets.where(
    (wallet) => wallet.chain.toUpperCase() == 'SOL',
  ).toList();

  for (final wallet in solanaWallets) {
    print('Address: ${wallet.address}');
  }

  return solanaWallets;
}

Solana Networks

Access configured Solana networks:
final sdk = DynamicSDK.instance;

void displaySolanaNetworks() {
  final solanaNetworks = sdk.networks.solana;

  for (final network in solanaNetworks) {
    print('Network: ${network.name}');
  }
}

Flutter Widget Example

import 'package:flutter/material.dart';
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:solana/solana.dart';

class SolanaBalanceWidget extends StatefulWidget {
  final BaseWallet wallet;

  const SolanaBalanceWidget({Key? key, required this.wallet}) : super(key: key);

  @override
  State<SolanaBalanceWidget> createState() => _SolanaBalanceWidgetState();
}

class _SolanaBalanceWidgetState extends State<SolanaBalanceWidget> {
  final sdk = DynamicSDK.instance;
  int? balance;
  bool isLoading = false;
  String? error;

  @override
  void initState() {
    super.initState();
    _fetchBalance();
  }

  Future<void> _fetchBalance() async {
    setState(() {
      isLoading = true;
      error = null;
    });

    try {
      final connection = sdk.solana.createConnection();
      final pubkey = Pubkey.fromString(widget.wallet.address);
      final balanceValue = await connection.getBalance(pubkey);

      setState(() => balance = balanceValue);
    } catch (e) {
      setState(() => error = 'Failed to fetch balance: $e');
    } finally {
      setState(() => isLoading = false);
    }
  }

  String formatBalance(int lamports) {
    final sol = lamports / 1e9;
    return '${sol.toStringAsFixed(4)} SOL';
  }

  @override
  Widget build(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              children: [
                const Text(
                  'Balance',
                  style: TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
                ),
                IconButton(
                  icon: const Icon(Icons.refresh),
                  onPressed: _fetchBalance,
                ),
              ],
            ),
            const SizedBox(height: 8),
            if (isLoading)
              const Center(child: CircularProgressIndicator())
            else if (balance != null)
              Text(
                formatBalance(balance!),
                style: const TextStyle(
                  fontSize: 24,
                  fontWeight: FontWeight.bold,
                ),
              )
            else if (error != null)
              Text(
                error!,
                style: const TextStyle(color: Colors.red, fontSize: 12),
              ),
          ],
        ),
      ),
    );
  }
}

Connection Methods

MethodDescription
createConnection()Create a Solana connection instance
getLatestBlockhash()Get the latest blockhash for transactions
getBalance(pubkey)Get account balance in lamports
getAccountInfo(pubkey)Get detailed account information

Balance Conversion Helpers

class SolanaConverter {
  /// Convert lamports to SOL
  static double lamportsToSol(int lamports) {
    return lamports / 1e9;
  }

  /// Convert SOL to lamports
  static int solToLamports(double sol) {
    return (sol * 1e9).toInt();
  }

  /// Format balance for display
  static String formatBalance(int lamports, {int decimals = 4}) {
    final sol = lamportsToSol(lamports);
    return '${sol.toStringAsFixed(decimals)} SOL';
  }
}

// Usage
final lamports = 1500000000; // 1.5 SOL
final formatted = SolanaConverter.formatBalance(lamports);
print(formatted); // "1.5000 SOL"

Complete Balance Display

import 'package:flutter/material.dart';
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:solana/solana.dart';

class SolanaAccountInfo extends StatelessWidget {
  final BaseWallet wallet;

  const SolanaAccountInfo({Key? key, required this.wallet}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<Map<String, dynamic>>(
      future: _getAccountInfo(),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const Center(child: CircularProgressIndicator());
        }

        if (snapshot.hasError) {
          return Text(
            'Error: ${snapshot.error}',
            style: const TextStyle(color: Colors.red),
          );
        }

        if (snapshot.hasData) {
          final data = snapshot.data!;
          return Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text('Address: ${data['address']}'),
              const SizedBox(height: 8),
              Text(
                'Balance: ${data['balance']}',
                style: const TextStyle(
                  fontSize: 20,
                  fontWeight: FontWeight.bold,
                ),
              ),
              const SizedBox(height: 8),
              Text('Blockhash: ${data['blockhash']}'),
            ],
          );
        }

        return const Text('No data available');
      },
    );
  }

  Future<Map<String, dynamic>> _getAccountInfo() async {
    final sdk = DynamicSDK.instance;
    final connection = sdk.solana.createConnection();

    final pubkey = Pubkey.fromString(wallet.address);
    final balance = await connection.getBalance(pubkey);
    final blockhash = await connection.getLatestBlockhash();

    return {
      'address': wallet.address,
      'balance': SolanaConverter.formatBalance(balance),
      'blockhash': blockhash.blockhash,
    };
  }
}

Error Handling

Future<int?> getBalanceSafely(String address) async {
  try {
    final sdk = DynamicSDK.instance;
    final connection = sdk.solana.createConnection();
    final pubkey = Pubkey.fromString(address);
    return await connection.getBalance(pubkey);
  } catch (e) {
    print('Failed to get balance: $e');
    return null;
  }
}

Dependencies

To build Solana transactions, ensure you have the required package:
dependencies:
  dynamic_sdk_solana: ^1.0.0
  solana: ^0.30.0

Next Steps