Overview

This guide covers balance operations including balance retrieval, Wei to ETH conversion, and balance formatting with the Dynamic Swift SDK.

Prerequisites

Balance Operations

Get Latest Balance and Convert to ETH

// Get latest balance (sample app usage)
do {
    let balanceWei = try await ethereumWallet.getBalance(.Latest)
    print("💰 Balance in Wei: \(balanceWei)")
    
    // Convert Wei to Ether (sample app conversion pattern)
    guard let etherValue = Double(String(balanceWei)) else {
        print("❌ Failed to convert balance to double")
        return
    }
    let etherInDecimals = etherValue / pow(10.0, 18.0)
    let balanceEth = String(format: "%.6f", etherInDecimals)
    
    print("💰 Balance in ETH: \(balanceEth)")
} catch {
    print("❌ Failed to fetch balance: \(error)")
}

Get Wallet Balance

// Get latest balance
do {
    let balanceWei = try await ethereumWallet.getBalance(.Latest)

    // Convert Wei to Ether
    let etherValue = Double(String(balanceWei)) ?? 0.0
    let balanceEth = etherValue / pow(10.0, 18.0)

    print("Balance: \(String(format: "%.6f", balanceEth)) ETH")
} catch {
    print("Failed to get balance: \(error)")
}

Balance Conversion Utilities

Wei to ETH Conversion

// Convert Wei to ETH with proper formatting
func weiToEth(_ wei: BigUInt, decimals: Int = 6) -> String {
    let etherValue = Double(String(wei)) ?? 0.0
    let ethValue = etherValue / pow(10.0, 18.0)
    return String(format: "%.\(decimals)f", ethValue)
}

// Usage
let balanceWei = try await ethereumWallet.getBalance(.Latest)
let balanceEth = weiToEth(balanceWei)
print("Balance: \(balanceEth) ETH")

ETH to Wei Conversion

// Convert ETH to Wei
func ethToWei(_ eth: Double) -> BigUInt {
    let weiValue = eth * pow(10.0, 18.0)
    return BigUInt(weiValue)
}

// Usage
let ethAmount = 1.5
let weiAmount = ethToWei(ethAmount)
print("\(ethAmount) ETH = \(weiAmount) Wei")

Gwei Conversions

// Convert Wei to Gwei
func weiToGwei(_ wei: BigUInt) -> Double {
    let gweiValue = Double(String(wei)) ?? 0.0
    return gweiValue / pow(10.0, 9.0) // 1 Gwei = 10^9 Wei
}

// Convert Gwei to Wei
func gweiToWei(_ gwei: Double) -> BigUInt {
    let weiValue = gwei * pow(10.0, 9.0)
    return BigUInt(weiValue)
}

// Usage
let gasPriceWei = try await networkClient.eth_gasPriceBigInt()
let gasPriceGwei = weiToGwei(gasPriceWei)
print("Gas Price: \(String(format: "%.2f", gasPriceGwei)) Gwei")

Balance Formatting

Format Balance for Display

// Format balance with appropriate units
func formatBalance(_ wei: BigUInt) -> String {
    let ethValue = Double(String(wei)) ?? 0.0
    let eth = ethValue / pow(10.0, 18.0)
    
    if eth >= 1.0 {
        return String(format: "%.4f ETH", eth)
    } else if eth >= 0.001 {
        return String(format: "%.6f ETH", eth)
    } else {
        let gwei = ethValue / pow(10.0, 9.0)
        return String(format: "%.2f Gwei", gwei)
    }
}

// Usage
let balanceWei = try await ethereumWallet.getBalance(.Latest)
let formattedBalance = formatBalance(balanceWei)
print("Balance: \(formattedBalance)")

Human-Readable Balance

// Create human-readable balance display
func humanReadableBalance(_ wei: BigUInt) -> String {
    let ethValue = Double(String(wei)) ?? 0.0
    let eth = ethValue / pow(10.0, 18.0)
    
    switch eth {
    case let x where x >= 1000:
        return String(format: "%.2f ETH", x)
    case let x where x >= 1:
        return String(format: "%.4f ETH", x)
    case let x where x >= 0.01:
        return String(format: "%.6f ETH", x)
    case let x where x >= 0.000001:
        let gwei = ethValue / pow(10.0, 9.0)
        return String(format: "%.2f Gwei", gwei)
    default:
        return "\(wei) Wei"
    }
}

// Usage
let balanceWei = try await ethereumWallet.getBalance(.Latest)
let humanBalance = humanReadableBalance(balanceWei)
print("Balance: \(humanBalance)")

Balance Monitoring

Real-Time Balance Updates

// Monitor balance changes
class BalanceMonitor {
    private var lastBalance: BigUInt = BigUInt(0)
    private let wallet: EthereumWallet
    
    init(wallet: EthereumWallet) {
        self.wallet = wallet
    }
    
    func startMonitoring() async {
        while true {
            do {
                let currentBalance = try await wallet.getBalance(.Latest)
                
                if currentBalance != lastBalance {
                    let change = currentBalance > lastBalance ? "+" : "-"
                    let difference = currentBalance > lastBalance ? 
                        currentBalance - lastBalance : 
                        lastBalance - currentBalance
                    
                    print("💰 Balance changed: \(change)\(weiToEth(difference)) ETH")
                    print("💰 New balance: \(weiToEth(currentBalance)) ETH")
                    
                    lastBalance = currentBalance
                }
                
                // Check every 30 seconds
                try await Task.sleep(nanoseconds: 30_000_000_000)
            } catch {
                print("❌ Failed to check balance: \(error)")
                break
            }
        }
    }
}

// Usage
let monitor = BalanceMonitor(wallet: ethereumWallet)
await monitor.startMonitoring()

Balance History Tracking

// Track balance history
struct BalanceEntry {
    let timestamp: Date
    let balanceWei: BigUInt
    let balanceEth: String
}

class BalanceTracker {
    private var balanceHistory: [BalanceEntry] = []
    
    func addBalanceEntry(_ wei: BigUInt) {
        let entry = BalanceEntry(
            timestamp: Date(),
            balanceWei: wei,
            balanceEth: weiToEth(wei)
        )
        balanceHistory.append(entry)
    }
    
    func getBalanceHistory() -> [BalanceEntry] {
        return balanceHistory
    }
    
    func getBalanceChange(duration: TimeInterval) -> BigUInt? {
        let cutoffDate = Date().addingTimeInterval(-duration)
        let recentEntries = balanceHistory.filter { $0.timestamp >= cutoffDate }
        
        guard let oldest = recentEntries.first,
              let newest = recentEntries.last else {
            return nil
        }
        
        return newest.balanceWei - oldest.balanceWei
    }
}

// Usage
let tracker = BalanceTracker()
let balanceWei = try await ethereumWallet.getBalance(.Latest)
tracker.addBalanceEntry(balanceWei)

// Check balance change in last hour
if let change = tracker.getBalanceChange(duration: 3600) {
    print("Balance change in last hour: \(weiToEth(change)) ETH")
}

Balance Validation

Check Sufficient Balance

// Check if wallet has sufficient balance for transaction
func hasSufficientBalance(
    wallet: EthereumWallet,
    amount: BigUInt,
    gasPrice: BigUInt,
    gasLimit: BigUInt
) async throws -> Bool {
    let balance = try await wallet.getBalance(.Latest)
    let totalCost = amount + (gasPrice * gasLimit)
    return balance >= totalCost
}

// Usage
let transactionAmount = BigUInt(1000000000000000000) // 1 ETH
let gasPrice = try await networkClient.eth_gasPriceBigInt()
let gasLimit = BigUInt(21_000)

do {
    let sufficient = try await hasSufficientBalance(
        wallet: ethereumWallet,
        amount: transactionAmount,
        gasPrice: gasPrice,
        gasLimit: gasLimit
    )
    
    if sufficient {
        print("✅ Sufficient balance for transaction")
    } else {
        print("❌ Insufficient balance for transaction")
    }
} catch {
    print("❌ Failed to check balance: \(error)")
}

Best Practices

1. Use Consistent Conversion Patterns

// Standard conversion pattern
let etherValue = Double(String(balanceWei)) ?? 0.0
let balanceEth = etherValue / pow(10.0, 18.0)
let formattedBalance = String(format: "%.6f", balanceEth)

2. Handle Large Numbers Properly

// Use BigUInt for large numbers to avoid overflow
let balanceWei: BigUInt = try await ethereumWallet.getBalance(.Latest)
let amountWei: BigUInt = BigUInt(1000000000000000000) // 1 ETH

// Safe arithmetic with BigUInt
let total = balanceWei + amountWei

3. Format for User Display

// Always format balances for user-friendly display
let rawBalance = try await ethereumWallet.getBalance(.Latest)
let displayBalance = humanReadableBalance(rawBalance)
print("Your balance: \(displayBalance)")

4. Monitor Balance Changes

// Monitor balance for important changes
let initialBalance = try await ethereumWallet.getBalance(.Latest)
// ... perform transaction ...
let finalBalance = try await ethereumWallet.getBalance(.Latest)

if finalBalance != initialBalance {
    let change = finalBalance > initialBalance ? 
        finalBalance - initialBalance : 
        initialBalance - finalBalance
    print("Balance changed by: \(weiToEth(change)) ETH")
}

Error Handling

do {
    let balance = try await ethereumWallet.getBalance(.Latest)
} catch {
    if let nsError = error as NSError? {
        switch nsError.code {
        case 6001:
            print("Network connection failed")
        case 6002:
            print("Invalid wallet address")
        case 6003:
            print("Balance query timeout")
        default:
            print("Balance error: \(error)")
        }
    }
}

Next Steps

After mastering balance operations, you can: