Overview
Estimate gas prices, manage EIP-1559 fees, and optimize transaction costs.Prerequisites
- Dynamic SDK initialized (see Installation Guide)
- User authenticated (see Authentication Guide)
- Wallets available (see Wallet Creation)
Get Current Gas Price
Copy
Ask AI
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.BaseWallet
import java.math.BigInteger
val sdk = DynamicSDK.getInstance()
suspend fun getCurrentGasPrice(chainId: Int): BigInteger {
val client = sdk.evm.createPublicClient(chainId)
val gasPrice = client.getGasPrice()
println("Current gas price: $gasPrice Wei")
return gasPrice
}
EIP-1559 Fee Management
Copy
Ask AI
import com.dynamic.sdk.android.Chains.EVM.EthereumTransaction
import com.dynamic.sdk.android.Chains.EVM.convertEthToWei
suspend fun createEip1559Transaction(
wallet: BaseWallet,
to: String,
amount: String,
chainId: Int
): EthereumTransaction {
val client = sdk.evm.createPublicClient(chainId)
val gasPrice = client.getGasPrice()
val maxPriorityFeePerGas = gasPrice
val maxFeePerGas = gasPrice * BigInteger.valueOf(2)
return EthereumTransaction(
from = wallet.address,
to = to,
value = convertEthToWei(amount),
gas = BigInteger.valueOf(21000),
maxFeePerGas = maxFeePerGas,
maxPriorityFeePerGas = maxPriorityFeePerGas
)
}
Gas Estimation ViewModel
Copy
Ask AI
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.dynamic.sdk.android.DynamicSDK
import com.dynamic.sdk.android.Models.BaseWallet
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch
import java.math.BigDecimal
import java.math.BigInteger
data class GasEstimate(
val gasLimit: BigInteger,
val gasPrice: BigInteger,
val maxFeePerGas: BigInteger,
val maxPriorityFeePerGas: BigInteger,
val estimatedCostInWei: BigInteger,
val estimatedCostInEth: String
)
class GasEstimationViewModel(private val wallet: BaseWallet) : ViewModel() {
private val sdk = DynamicSDK.getInstance()
private val _gasEstimate = MutableStateFlow<GasEstimate?>(null)
val gasEstimate: StateFlow<GasEstimate?> = _gasEstimate.asStateFlow()
private val _isLoading = MutableStateFlow(false)
val isLoading: StateFlow<Boolean> = _isLoading.asStateFlow()
private val _errorMessage = MutableStateFlow<String?>(null)
val errorMessage: StateFlow<String?> = _errorMessage.asStateFlow()
fun estimateGas(
chainId: Int,
gasLimit: BigInteger = BigInteger.valueOf(21000)
) {
viewModelScope.launch {
_isLoading.value = true
_errorMessage.value = null
try {
val client = sdk.evm.createPublicClient(chainId)
val gasPrice = client.getGasPrice()
val maxPriorityFeePerGas = gasPrice
val maxFeePerGas = gasPrice * BigInteger.valueOf(2)
val estimatedCostWei = gasLimit * maxFeePerGas
val weiPerEth = BigDecimal("1000000000000000000")
val estimatedCostEth = BigDecimal(estimatedCostWei).divide(weiPerEth).toPlainString()
_gasEstimate.value = GasEstimate(
gasLimit, gasPrice, maxFeePerGas, maxPriorityFeePerGas,
estimatedCostWei, estimatedCostEth
)
} catch (e: Exception) {
_errorMessage.value = "Failed to estimate gas: ${e.message}"
}
_isLoading.value = false
}
}
fun convertWeiToGwei(wei: BigInteger): String {
val weiPerGwei = BigDecimal("1000000000")
return BigDecimal(wei).divide(weiPerGwei).toPlainString()
}
fun convertGweiToWei(gwei: String): BigInteger {
val weiPerGwei = BigDecimal("1000000000")
return BigDecimal(gwei).multiply(weiPerGwei).toBigInteger()
}
}
Jetpack Compose UI for Gas Display
Copy
Ask AI
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
@Composable
fun GasEstimateCard(gasEstimate: GasEstimate?) {
gasEstimate?.let { estimate ->
Card(
modifier = Modifier.fillMaxWidth(),
colors = CardDefaults.cardColors(
containerColor = MaterialTheme.colorScheme.surfaceVariant
)
) {
Column(modifier = Modifier.padding(16.dp)) {
Text(
text = "Gas Estimate",
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(12.dp))
GasInfoRow(
label = "Gas Limit",
value = estimate.gasLimit.toString()
)
GasInfoRow(
label = "Max Fee Per Gas",
value = "${convertWeiToGwei(estimate.maxFeePerGas)} Gwei"
)
GasInfoRow(
label = "Max Priority Fee",
value = "${convertWeiToGwei(estimate.maxPriorityFeePerGas)} Gwei"
)
Divider(modifier = Modifier.padding(vertical = 8.dp))
GasInfoRow(
label = "Estimated Cost",
value = "${estimate.estimatedCostInEth} ETH",
valueStyle = MaterialTheme.typography.titleSmall
)
}
}
}
}
@Composable
fun GasInfoRow(
label: String,
value: String,
valueStyle: androidx.compose.ui.text.TextStyle = MaterialTheme.typography.bodyMedium
) {
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
Text(
text = label,
style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
Text(
text = value,
style = valueStyle
)
}
}
fun convertWeiToGwei(wei: BigInteger): String {
val weiPerGwei = BigDecimal("1000000000")
return BigDecimal(wei).divide(weiPerGwei).setScale(2).toPlainString()
}
Gas Optimization Strategies
1. Standard Gas Limits by Transaction Type
Copy
Ask AI
object GasLimits {
val ETH_TRANSFER = BigInteger.valueOf(21000)
val ERC20_TRANSFER = BigInteger.valueOf(65000)
val ERC721_TRANSFER = BigInteger.valueOf(85000)
val UNISWAP_SWAP = BigInteger.valueOf(200000)
val CONTRACT_DEPLOYMENT = BigInteger.valueOf(1000000)
fun forTransactionType(type: TransactionType): BigInteger {
return when (type) {
TransactionType.ETH_TRANSFER -> ETH_TRANSFER
TransactionType.ERC20_TRANSFER -> ERC20_TRANSFER
TransactionType.ERC721_TRANSFER -> ERC721_TRANSFER
TransactionType.UNISWAP_SWAP -> UNISWAP_SWAP
TransactionType.CONTRACT_DEPLOYMENT -> CONTRACT_DEPLOYMENT
}
}
}
enum class TransactionType {
ETH_TRANSFER,
ERC20_TRANSFER,
ERC721_TRANSFER,
UNISWAP_SWAP,
CONTRACT_DEPLOYMENT
}
2. Dynamic Gas Price Adjustment
Copy
Ask AI
suspend fun getGasWithStrategy(
chainId: Int,
strategy: GasStrategy
): Pair<BigInteger, BigInteger> {
val client = sdk.evm.createPublicClient(chainId)
val baseGasPrice = client.getGasPrice()
return when (strategy) {
GasStrategy.SLOW -> {
val maxFeePerGas = baseGasPrice * BigInteger.valueOf(1)
val maxPriorityFeePerGas = baseGasPrice / BigInteger.valueOf(2)
Pair(maxFeePerGas, maxPriorityFeePerGas)
}
GasStrategy.STANDARD -> {
val maxFeePerGas = baseGasPrice * BigInteger.valueOf(2)
val maxPriorityFeePerGas = baseGasPrice
Pair(maxFeePerGas, maxPriorityFeePerGas)
}
GasStrategy.FAST -> {
val maxFeePerGas = baseGasPrice * BigInteger.valueOf(3)
val maxPriorityFeePerGas = baseGasPrice * BigInteger.valueOf(2)
Pair(maxFeePerGas, maxPriorityFeePerGas)
}
}
}
enum class GasStrategy {
SLOW,
STANDARD,
FAST
}
3. Gas Strategy Selector UI
Copy
Ask AI
@Composable
fun GasStrategySelector(
selectedStrategy: GasStrategy,
onStrategyChange: (GasStrategy) -> Unit,
gasEstimates: Map<GasStrategy, String>
) {
Column(modifier = Modifier.fillMaxWidth()) {
Text(
text = "Transaction Speed",
style = MaterialTheme.typography.titleMedium
)
Spacer(modifier = Modifier.height(8.dp))
GasStrategy.values().forEach { strategy ->
Row(
modifier = Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
horizontalArrangement = Arrangement.SpaceBetween
) {
RadioButton(
selected = selectedStrategy == strategy,
onClick = { onStrategyChange(strategy) }
)
Column(modifier = Modifier.weight(1f)) {
Text(
text = strategy.name.lowercase().replaceFirstChar { it.uppercase() },
style = MaterialTheme.typography.bodyLarge
)
Text(
text = gasEstimates[strategy] ?: "Calculating...",
style = MaterialTheme.typography.bodySmall,
color = MaterialTheme.colorScheme.onSurfaceVariant
)
}
}
}
}
}
Unit Conversion Utilities
Copy
Ask AI
object GasConverter {
private val WEI_PER_GWEI = BigDecimal("1000000000")
private val WEI_PER_ETH = BigDecimal("1000000000000000000")
fun weiToGwei(wei: BigInteger): String {
return BigDecimal(wei)
.divide(WEI_PER_GWEI)
.setScale(2, java.math.RoundingMode.HALF_UP)
.toPlainString()
}
fun gweiToWei(gwei: String): BigInteger {
return BigDecimal(gwei)
.multiply(WEI_PER_GWEI)
.toBigInteger()
}
fun weiToEth(wei: BigInteger): String {
return BigDecimal(wei)
.divide(WEI_PER_ETH)
.setScale(6, java.math.RoundingMode.HALF_UP)
.toPlainString()
}
fun ethToWei(eth: String): BigInteger {
return BigDecimal(eth)
.multiply(WEI_PER_ETH)
.toBigInteger()
}
fun calculateTransactionCost(gasLimit: BigInteger, gasPrice: BigInteger): String {
val costInWei = gasLimit * gasPrice
return weiToEth(costInWei)
}
}
// Usage
val gasPriceInGwei = GasConverter.weiToGwei(gasPrice)
val costInEth = GasConverter.calculateTransactionCost(gasLimit, maxFeePerGas)
Best Practices
- Always show gas estimates before transactions
- Include total cost (amount + gas) in confirmations
- Adjust gas price based on urgency (low/medium/high)
- Set maximum gas limits to prevent excessive fees
- Monitor gas prices for network congestion
- Validate gas limits are within acceptable range
Error Handling
Copy
Ask AI
sealed class GasError {
data class PriceTooHigh(val gasPrice: BigInteger, val maxAllowed: BigInteger) : GasError()
data class InsufficientFunds(val required: BigInteger, val available: BigInteger) : GasError()
data class NetworkError(val message: String) : GasError()
data class Unknown(val message: String) : GasError()
}
suspend fun checkGasAffordability(
wallet: BaseWallet,
chainId: Int,
gasLimit: BigInteger,
gasPrice: BigInteger
): Result<Unit> {
return try {
val client = sdk.evm.createPublicClient(chainId)
val balance = client.getBalance(wallet.address)
val gasCost = gasLimit * gasPrice
if (balance < gasCost) {
Result.failure(
Exception("Insufficient funds for gas: ${GasConverter.weiToEth(gasCost)} ETH required")
)
} else {
Result.success(Unit)
}
} catch (e: Exception) {
Result.failure(e)
}
}
Troubleshooting
Gas price too low: Increase multiplier from 2x to 3x Out of gas: Increase gas limit, especially for contract calls Contract gas estimation: Use higher estimates for complex operations (swap, mint)What’s Next
- Send ETH Transactions - Send native ETH with gas management
- ERC-20 Token Transfers - Transfer tokens with gas optimization
- Smart Contract Interactions - Estimate gas for contract calls
- Network Management - Switch between networks