Overview

This guide covers gas management including gas price retrieval, gas limits, and gas optimization with the Dynamic Swift SDK.

Prerequisites

Gas Management

Get Current Gas Price

let networkClient = try await ethereumWallet.getNetworkClient(for: chainId)

do {
    let gasPrice = try await networkClient.eth_gasPriceBigInt()
    print("Current gas price: \(gasPrice) wei")
} catch {
    print("Failed to get gas price: \(error)")
}

Gas Limit for ETH Transfers

// Standard gas limit for ETH transfers (used in sample app)
let gasLimit = BigUInt(21_000) // Standard ETH transfer
print("ETH Transfer Gas Limit: \(gasLimit)")

Gas Price Management

Get Network Gas Price

let dynamicClient: DynamicClient
let ethereumWallet: EthereumWallet
let chainId = SupportedEthereumNetwork.sepoliaTestnet.chainConfig.chainId

do {
    let networkClient = try await ethereumWallet.getNetworkClient(for: chainId)
    print("Connected to Sepolia network: \(chainId)")
    
    // Get gas price for transactions
    let gasPrice = try await networkClient.eth_gasPriceBigInt()
    print("Current gas price: \(gasPrice) wei")
} catch {
    print("Failed to get network client: \(error)")
}

Convert Gas Price to Gwei

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

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

Gas Limit Management

Standard Gas Limits

// Common gas limits for different transaction types
struct GasLimits {
    static let ethTransfer = BigUInt(21_000)      // Standard ETH transfer
    static let erc20Transfer = BigUInt(65_000)    // ERC-20 token transfer
    static let contractDeploy = BigUInt(500_000)  // Contract deployment
    static let contractCall = BigUInt(100_000)    // Contract function call
}

// Usage
let gasLimit = GasLimits.ethTransfer
print("Using standard ETH transfer gas limit: \(gasLimit)")

Estimate Gas Limit

// Estimate gas for complex transactions
func estimateGasForTransaction(_ transaction: EthereumTransaction) async throws -> BigUInt {
    let networkClient = try await ethereumWallet.getNetworkClient(for: transaction.chainId)
    return try await networkClient.eth_estimateGas(transaction)
}

// Usage
let transaction = EthereumTransaction(
    from: ethereumWallet.address,
    to: recipient,
    value: amount,
    data: Data(),
    nonce: nil,
    gasPrice: gasPrice,
    gasLimit: nil, // Will be estimated
    chainId: chainId
)

do {
    let estimatedGas = try await estimateGasForTransaction(transaction)
    print("Estimated gas: \(estimatedGas)")
    
    // Add buffer for safety (20% buffer)
    let gasWithBuffer = estimatedGas + (estimatedGas / 5)
    print("Gas with buffer: \(gasWithBuffer)")
} catch {
    print("Failed to estimate gas: \(error)")
}

Gas Optimization

Dynamic Gas Pricing

// Get optimal gas price based on network conditions
func getOptimalGasPrice() async throws -> BigUInt {
    let networkClient = try await ethereumWallet.getNetworkClient(for: chainId)
    let currentGasPrice = try await networkClient.eth_gasPriceBigInt()
    
    // Add 10% buffer for faster confirmation
    let optimalGasPrice = currentGasPrice + (currentGasPrice / 10)
    return optimalGasPrice
}

// Usage
do {
    let optimalGasPrice = try await getOptimalGasPrice()
    print("Optimal gas price: \(optimalGasPrice) wei")
} catch {
    print("Failed to get optimal gas price: \(error)")
}

Gas Price Strategies

enum GasStrategy {
    case low      // Slow but cheap
    case medium   // Balanced
    case high     // Fast but expensive
}

func getGasPriceForStrategy(_ strategy: GasStrategy, basePrice: BigUInt) -> BigUInt {
    switch strategy {
    case .low:
        return basePrice - (basePrice / 10) // 10% below base
    case .medium:
        return basePrice // Use base price
    case .high:
        return basePrice + (basePrice / 5) // 20% above base
    }
}

// Usage
let baseGasPrice = try await networkClient.eth_gasPriceBigInt()
let fastGasPrice = getGasPriceForStrategy(.high, basePrice: baseGasPrice)
print("Fast gas price: \(fastGasPrice) wei")

Transaction Gas Management

Create Transaction with Gas

let fromAddress = ethereumWallet.address
let toAddress = EthereumAddress("0xRecipientAddress")
let amount = BigUInt(1000000000000000000) // 1 ETH in wei
let gasPrice = try await networkClient.eth_gasPriceBigInt()
let gasLimit = BigUInt(21_000)
let chainId = SupportedEthereumNetwork.sepoliaTestnet.chainConfig.chainId

let transaction = EthereumTransaction(
    from: fromAddress,
    to: toAddress,
    value: amount,
    data: Data(),
    nonce: nil,
    gasPrice: gasPrice,
    gasLimit: gasLimit,
    chainId: chainId
)

Calculate Transaction Cost

// Calculate total transaction cost in ETH
func calculateTransactionCost(gasPrice: BigUInt, gasLimit: BigUInt) -> Double {
    let totalWei = gasPrice * gasLimit
    let totalEth = Double(String(totalWei)) ?? 0.0
    return totalEth / pow(10.0, 18.0)
}

// Usage
let gasPrice = try await networkClient.eth_gasPriceBigInt()
let gasLimit = BigUInt(21_000)
let cost = calculateTransactionCost(gasPrice: gasPrice, gasLimit: gasLimit)
print("Transaction cost: \(String(format: "%.6f", cost)) ETH")

Best Practices

1. Always Get Current Gas Price

// Always get current gas price before sending transactions
let gasPrice = try await networkClient.eth_gasPriceBigInt()
let gasLimit = BigUInt(21_000) // Standard ETH transfer

// For complex transactions, estimate gas limit
let estimatedGas = try await networkClient.eth_estimateGas(transaction)

2. Use Appropriate Gas Limits

// Use standard limits for simple transactions
let gasLimit = GasLimits.ethTransfer

// Estimate for complex transactions
let estimatedGas = try await estimateGasForTransaction(transaction)
let gasWithBuffer = estimatedGas + (estimatedGas / 5) // 20% buffer

3. Monitor Gas Prices

// Monitor gas prices for optimal timing
func monitorGasPrices() async {
    while true {
        do {
            let gasPrice = try await networkClient.eth_gasPriceBigInt()
            let gasPriceGwei = weiToGwei(gasPrice)
            print("Current gas price: \(String(format: "%.2f", gasPriceGwei)) Gwei")
            
            // Wait 30 seconds before next check
            try await Task.sleep(nanoseconds: 30_000_000_000)
        } catch {
            print("Failed to get gas price: \(error)")
            break
        }
    }
}

Error Handling

do {
    let gasPrice = try await networkClient.eth_gasPriceBigInt()
} catch {
    if let nsError = error as NSError? {
        switch nsError.code {
        case 5001:
            print("Gas price too high")
        case 5002:
            print("Gas limit exceeded")
        case 5003:
            print("Insufficient gas for transaction")
        default:
            print("Gas error: \(error)")
        }
    }
}

Next Steps

After mastering gas management, you can: