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 DynamicSDKSwift
let sdk = DynamicSDK.instance()
func getBalance(wallet: BaseWallet) async {
do {
let balance = try await sdk.wallets.getBalance(wallet: wallet)
print("Balance: \(balance)")
} catch {
print("Failed to get balance: \(error)")
}
}
Display Balance with SwiftUI
import SwiftUI
import DynamicSDKSwift
@MainActor
class WalletBalanceViewModel: ObservableObject {
@Published var balance: String?
@Published var isLoading = false
@Published var errorMessage: String?
private let sdk = DynamicSDK.instance()
func fetchBalance(wallet: BaseWallet) {
isLoading = true
errorMessage = nil
Task {
do {
balance = try await sdk.wallets.getBalance(wallet: wallet)
} catch {
errorMessage = "Failed to get balance: \(error.localizedDescription)"
}
isLoading = false
}
}
}
struct WalletBalanceView: View {
let wallet: BaseWallet
@StateObject private var viewModel = WalletBalanceViewModel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("Balance")
.font(.caption)
.foregroundColor(.secondary)
if viewModel.isLoading {
HStack {
ProgressView()
Text("Loading...")
.foregroundColor(.secondary)
}
} else if let balance = viewModel.balance {
Text(balance)
.font(.headline)
} else if let error = viewModel.errorMessage {
Text(error)
.foregroundColor(.red)
.font(.caption)
}
}
.onAppear {
viewModel.fetchBalance(wallet: wallet)
}
}
}
EVM Balance Conversions
Wei to ETH Conversion
import BigInt
/// Convert Wei to ETH
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: BigUInt = 1500000000000000000 // 1.5 ETH
let balanceEth = weiToEth(balanceWei)
print("Balance: \(balanceEth) ETH")
ETH to Wei Conversion
import BigInt
/// 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
import BigInt
/// 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 for gas prices
let gasPriceGwei = 50.0
let gasPriceWei = gweiToWei(gasPriceGwei)
print("Gas Price: \(gasPriceGwei) Gwei = \(gasPriceWei) Wei")
import BigInt
/// Format EVM balance with appropriate units
func formatEvmBalance(_ 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)
}
}
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
func lamportsToSol(_ lamports: UInt64, decimals: Int = 6) -> String {
let solValue = Double(lamports) / 1_000_000_000.0
return String(format: "%.\(decimals)f", solValue)
}
// Usage
let balanceLamports: UInt64 = 1_500_000_000 // 1.5 SOL
let balanceSol = lamportsToSol(balanceLamports)
print("Balance: \(balanceSol) SOL")
SOL to Lamports Conversion
/// Convert SOL to lamports
func solToLamports(_ sol: Double) -> UInt64 {
return UInt64(sol * 1_000_000_000)
}
// Usage
let solAmount = 1.5
let lamportsAmount = solToLamports(solAmount)
print("\(solAmount) SOL = \(lamportsAmount) lamports")
/// Format SOL balance for display
func formatSolBalance(_ lamports: UInt64) -> String {
let sol = Double(lamports) / 1_000_000_000.0
if sol >= 1.0 {
return String(format: "%.4f SOL", sol)
} else if sol >= 0.001 {
return String(format: "%.6f SOL", sol)
} else {
return String(format: "%.9f SOL", sol)
}
}
Multi-Chain Balance Display
Handle balances for both EVM and Solana wallets:
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func displayBalance(wallet: BaseWallet) async {
do {
let balance = try await sdk.wallets.getBalance(wallet: wallet)
let chain = wallet.chain.uppercased()
switch chain {
case "EVM":
print("Balance: \(balance) (in Wei)")
case "SOL":
print("Balance: \(balance) (in lamports)")
default:
print("Balance: \(balance)")
}
} catch {
print("Failed to get balance: \(error)")
}
}
// Display all wallet balances
func displayAllBalances() async {
for wallet in sdk.wallets.userWallets {
print("\(wallet.chain) wallet: \(wallet.address)")
await displayBalance(wallet: wallet)
}
}
Conversion Helper Class
import BigInt
/// Helper class for balance conversions
struct BalanceConverter {
/// EVM conversions
static func weiToEth(_ wei: BigUInt) -> Double {
let ethValue = Double(String(wei)) ?? 0.0
return ethValue / pow(10.0, 18.0)
}
static func ethToWei(_ eth: Double) -> BigUInt {
return BigUInt(eth * pow(10.0, 18.0))
}
static func weiToGwei(_ wei: BigUInt) -> Double {
let gweiValue = Double(String(wei)) ?? 0.0
return gweiValue / pow(10.0, 9.0)
}
/// Solana conversions
static func lamportsToSol(_ lamports: UInt64) -> Double {
return Double(lamports) / 1_000_000_000.0
}
static func solToLamports(_ sol: Double) -> UInt64 {
return UInt64(sol * 1_000_000_000)
}
/// Format for display
static func formatBalance(
value: String,
chain: String,
decimals: Int = 4
) -> String {
switch chain.uppercased() {
case "EVM":
if let wei = BigUInt(value) {
let eth = weiToEth(wei)
return String(format: "%.\(decimals)f ETH", eth)
}
case "SOL":
if let lamports = UInt64(value) {
let sol = lamportsToSol(lamports)
return String(format: "%.\(decimals)f SOL", sol)
}
default:
break
}
return value
}
}
// Usage
let formatted = BalanceConverter.formatBalance(
value: "1500000000000000000",
chain: "EVM",
decimals: 4
)
print(formatted) // "1.5000 ETH"
Common Token Decimals
| Chain | Token | Decimals | Unit |
|---|
| EVM | ETH | 18 | Wei |
| EVM | USDC | 6 | Smallest unit |
| EVM | USDT | 6 | Smallest unit |
| EVM | WBTC | 8 | Smallest unit |
| Solana | SOL | 9 | Lamports |
Best Practices
1. Cache Balances
@MainActor
class BalanceCache: ObservableObject {
@Published var balances: [String: String] = [:]
private let sdk = DynamicSDK.instance()
func refreshBalance(for wallet: BaseWallet) async {
do {
let balance = try await sdk.wallets.getBalance(wallet: wallet)
balances[wallet.address] = balance
} catch {
print("Failed to refresh balance: \(error)")
}
}
func refreshAllBalances() async {
for wallet in sdk.wallets.userWallets {
await refreshBalance(for: wallet)
}
}
}
2. Handle Precision
// Use BigUInt for EVM to avoid precision loss
import BigInt
let wei = BigUInt("1500000000000000000")! // 1.5 ETH
let eth = BalanceConverter.weiToEth(wei)
// Use UInt64 for Solana
let lamports: UInt64 = 1_500_000_000 // 1.5 SOL
let sol = BalanceConverter.lamportsToSol(lamports)
3. Refresh After Transactions
func sendTransactionAndRefresh(wallet: BaseWallet) async {
do {
// Send transaction
let txHash = try await sendTransaction(wallet: wallet)
// Wait a moment for blockchain confirmation
try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
// Refresh balance
let newBalance = try await sdk.wallets.getBalance(wallet: wallet)
print("New balance: \(newBalance)")
} catch {
print("Error: \(error)")
}
}
Next Steps