Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt

Use this file to discover all available pages before exploring further.

Overview

This guide covers balance operations for both EVM and Solana chains, including balance retrieval, conversion utilities, and formatting.

Prerequisites

Get Wallet Balance

The SDK provides a unified method to get balance for any wallet type:
import 'package:dynamic_sdk/dynamic_sdk.dart';

final sdk = DynamicSDK.instance;

Future<String> getBalance(BaseWallet wallet) async {
  try {
    final balance = await sdk.wallets.getBalance(wallet: wallet);
    print('Balance: $balance');
    return balance;
  } catch (e) {
    print('Failed to get balance: $e');
    rethrow;
  }
}

Display Balance with Flutter

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

class WalletBalanceWidget extends StatefulWidget {
  final BaseWallet wallet;

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

  @override
  State<WalletBalanceWidget> createState() => _WalletBalanceWidgetState();
}

class _WalletBalanceWidgetState extends State<WalletBalanceWidget> {
  final sdk = DynamicSDK.instance;
  String? balance;
  bool isLoading = false;
  String? errorMessage;

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

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

    try {
      final balanceValue = await sdk.wallets.getBalance(wallet: widget.wallet);
      setState(() => balance = balanceValue);
    } catch (e) {
      setState(() => errorMessage = 'Failed to get balance: $e');
    } finally {
      setState(() => isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        const Text(
          'Balance',
          style: TextStyle(fontSize: 12, color: Colors.grey),
        ),
        const SizedBox(height: 8),
        if (isLoading)
          const Row(
            children: [
              SizedBox(
                width: 16,
                height: 16,
                child: CircularProgressIndicator(strokeWidth: 2),
              ),
              SizedBox(width: 8),
              Text('Loading...', style: TextStyle(color: Colors.grey)),
            ],
          )
        else if (balance != null)
          Text(
            balance!,
            style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
          )
        else if (errorMessage != null)
          Text(
            errorMessage!,
            style: const TextStyle(fontSize: 12, color: Colors.red),
          ),
      ],
    );
  }
}

EVM Balance Conversions

Wei to ETH Conversion

import 'package:web3dart/web3dart.dart';

/// Convert Wei to ETH
String weiToEth(BigInt wei, {int decimals = 6}) {
  final ethValue = wei / BigInt.from(10).pow(18);
  return ethValue.toStringAsFixed(decimals);
}

// Usage
final balanceWei = BigInt.from(1500000000000000000); // 1.5 ETH
final balanceEth = weiToEth(balanceWei);
print('Balance: $balanceEth ETH');

ETH to Wei Conversion

import 'package:web3dart/web3dart.dart';

/// Convert ETH to Wei
BigInt ethToWei(double eth) {
  return BigInt.from(eth * 1e18);
}

// Usage
final ethAmount = 1.5;
final weiAmount = ethToWei(ethAmount);
print('$ethAmount ETH = $weiAmount Wei');

Gwei Conversions

/// Convert Wei to Gwei
double weiToGwei(BigInt wei) {
  return wei.toDouble() / 1e9; // 1 Gwei = 10^9 Wei
}

/// Convert Gwei to Wei
BigInt gweiToWei(double gwei) {
  return BigInt.from(gwei * 1e9);
}

// Usage for gas prices
final gasPriceGwei = 50.0;
final gasPriceWei = gweiToWei(gasPriceGwei);
print('Gas Price: $gasPriceGwei Gwei = $gasPriceWei Wei');

Balance Formatting

/// Format EVM balance with appropriate units
String formatEvmBalance(BigInt wei) {
  final eth = wei.toDouble() / 1e18;

  if (eth >= 1.0) {
    return '${eth.toStringAsFixed(4)} ETH';
  } else if (eth >= 0.001) {
    return '${eth.toStringAsFixed(6)} ETH';
  } else {
    final gwei = wei.toDouble() / 1e9;
    return '${gwei.toStringAsFixed(2)} Gwei';
  }
}

Solana Balance Conversions

Solana uses lamports as its smallest unit, where 1 SOL = 10^9 lamports (9 decimal places).

Lamports to SOL Conversion

/// Convert lamports to SOL
String lamportsToSol(int lamports, {int decimals = 6}) {
  final solValue = lamports / 1e9;
  return solValue.toStringAsFixed(decimals);
}

// Usage
final balanceLamports = 1500000000; // 1.5 SOL
final balanceSol = lamportsToSol(balanceLamports);
print('Balance: $balanceSol SOL');

SOL to Lamports Conversion

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

// Usage
final solAmount = 1.5;
final lamportsAmount = solToLamports(solAmount);
print('$solAmount SOL = $lamportsAmount lamports');

SOL Balance Formatting

/// Format SOL balance for display
String formatSolBalance(int lamports) {
  final sol = lamports / 1e9;

  if (sol >= 1.0) {
    return '${sol.toStringAsFixed(4)} SOL';
  } else if (sol >= 0.001) {
    return '${sol.toStringAsFixed(6)} SOL';
  } else {
    return '${sol.toStringAsFixed(9)} SOL';
  }
}

Multi-Chain Balance Display

Handle balances for both EVM and Solana wallets:
import 'package:dynamic_sdk/dynamic_sdk.dart';

final sdk = DynamicSDK.instance;

Future<void> displayBalance(BaseWallet wallet) async {
  try {
    final balance = await sdk.wallets.getBalance(wallet: wallet);
    final chain = wallet.chain.toUpperCase();

    switch (chain) {
      case 'EVM':
        print('Balance: $balance (in Wei)');
        break;
      case 'SOL':
        print('Balance: $balance (in lamports)');
        break;
      default:
        print('Balance: $balance');
    }
  } catch (e) {
    print('Failed to get balance: $e');
  }
}

// Display all wallet balances
Future<void> displayAllBalances() async {
  for (final wallet in sdk.wallets.userWallets) {
    print('${wallet.chain} wallet: ${wallet.address}');
    await displayBalance(wallet);
  }
}

Conversion Helper Class

/// Helper class for balance conversions
class BalanceConverter {
  /// EVM conversions
  static double weiToEth(BigInt wei) {
    return wei.toDouble() / 1e18;
  }

  static BigInt ethToWei(double eth) {
    return BigInt.from(eth * 1e18);
  }

  static double weiToGwei(BigInt wei) {
    return wei.toDouble() / 1e9;
  }

  /// Solana conversions
  static double lamportsToSol(int lamports) {
    return lamports / 1e9;
  }

  static int solToLamports(double sol) {
    return (sol * 1e9).toInt();
  }

  /// Format for display
  static String formatBalance({
    required String value,
    required String chain,
    int decimals = 4,
  }) {
    switch (chain.toUpperCase()) {
      case 'EVM':
        final wei = BigInt.tryParse(value);
        if (wei != null) {
          final eth = weiToEth(wei);
          return '${eth.toStringAsFixed(decimals)} ETH';
        }
        break;
      case 'SOL':
        final lamports = int.tryParse(value);
        if (lamports != null) {
          final sol = lamportsToSol(lamports);
          return '${sol.toStringAsFixed(decimals)} SOL';
        }
        break;
    }
    return value;
  }
}

// Usage
final formatted = BalanceConverter.formatBalance(
  value: '1500000000000000000',
  chain: 'EVM',
  decimals: 4,
);
print(formatted); // "1.5000 ETH"

Common Token Decimals

ChainTokenDecimalsUnit
EVMETH18Wei
EVMUSDC6Smallest unit
EVMUSDT6Smallest unit
EVMWBTC8Smallest unit
SolanaSOL9Lamports

Best Practices

1. Cache Balances

import 'package:flutter/foundation.dart';
import 'package:dynamic_sdk/dynamic_sdk.dart';

class BalanceCache extends ChangeNotifier {
  final Map<String, String> _balances = {};
  final sdk = DynamicSDK.instance;

  Map<String, String> get balances => _balances;

  Future<void> refreshBalance(BaseWallet wallet) async {
    try {
      final balance = await sdk.wallets.getBalance(wallet: wallet);
      _balances[wallet.address] = balance;
      notifyListeners();
    } catch (e) {
      print('Failed to refresh balance: $e');
    }
  }

  Future<void> refreshAllBalances() async {
    for (final wallet in sdk.wallets.userWallets) {
      await refreshBalance(wallet);
    }
  }
}

2. Handle Precision

// Use BigInt for EVM to avoid precision loss
final wei = BigInt.parse('1500000000000000000'); // 1.5 ETH
final eth = BalanceConverter.weiToEth(wei);

// Use int for Solana
final lamports = 1500000000; // 1.5 SOL
final sol = BalanceConverter.lamportsToSol(lamports);

3. Refresh After Transactions

Future<void> sendTransactionAndRefresh(BaseWallet wallet) async {
  try {
    // Send transaction
    final txHash = await sendTransaction(wallet: wallet);
    print('Transaction sent: $txHash');

    // Wait a moment for blockchain confirmation
    await Future.delayed(const Duration(seconds: 2));

    // Refresh balance
    final newBalance = await sdk.wallets.getBalance(wallet: wallet);
    print('New balance: $newBalance');
  } catch (e) {
    print('Error: $e');
  }
}

FutureBuilder Example

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

class BalanceDisplay extends StatelessWidget {
  final BaseWallet wallet;

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

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<String>(
      future: DynamicSDK.instance.wallets.getBalance(wallet: wallet),
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.waiting) {
          return const CircularProgressIndicator();
        }

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

        if (snapshot.hasData) {
          final formatted = BalanceConverter.formatBalance(
            value: snapshot.data!,
            chain: wallet.chain,
          );
          return Text(
            formatted,
            style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
          );
        }

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

Next Steps