CW-802: Ethereum enhancements (#1826)

* fix: Ethereum enhancements around fees and computations relating to signing and sending transactions

* feat: Add nownodes key for evm to workflow

* feat: Reactivate send all on both eth and polygon wallet types

* fix: Add generic function for updating the node for a wallet type, move ethereum transaction error fees handler to a new file

* fix: Revert podfile.lock

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke 2024-12-11 15:45:15 +01:00 committed by GitHub
parent ed600f9b8b
commit 9590aa25b6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
40 changed files with 346 additions and 35 deletions

View file

@ -221,7 +221,7 @@ abstract class EVMChainWalletBase
/// - The exact amount the user wants to send,
/// - The addressHex for the receiving wallet,
/// - A contract address which would be essential in determining if to calcualate the estimate for ERC20 or native ETH
Future<int> calculateActualEstimatedFeeForCreateTransaction({
Future<GasParamsHandler> calculateActualEstimatedFeeForCreateTransaction({
required amount,
required String? contractAddress,
required String receivingAddressHex,
@ -240,22 +240,27 @@ abstract class EVMChainWalletBase
maxFeePerGas = gasPrice;
}
final estimatedGas = await _client.getEstimatedGas(
final estimatedGas = await _client.getEstimatedGasUnitsForTransaction(
contractAddress: contractAddress,
senderAddress: _evmChainPrivateKey.address,
value: EtherAmount.fromBigInt(EtherUnit.wei, amount!),
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
toAddress: EthereumAddress.fromHex(receivingAddressHex),
// maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
// maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip),
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
);
final totalGasFee = estimatedGas * maxFeePerGas;
return totalGasFee;
return GasParamsHandler(
estimatedGasUnits: estimatedGas,
estimatedGasFee: totalGasFee,
maxFeePerGas: maxFeePerGas,
gasPrice: gasPrice,
);
}
return 0;
return GasParamsHandler.zero();
} catch (e) {
return 0;
return GasParamsHandler.zero();
}
}
@ -318,7 +323,7 @@ abstract class EVMChainWalletBase
gasPrice = await _client.getGasUnitPrice();
estimatedGasUnits = await _client.getEstimatedGas(
estimatedGasUnits = await _client.getEstimatedGasUnitsForTransaction(
senderAddress: _evmChainPrivateKey.address,
toAddress: _evmChainPrivateKey.address,
gasPrice: EtherAmount.fromInt(EtherUnit.wei, gasPrice),
@ -349,6 +354,8 @@ abstract class EVMChainWalletBase
int exponent = transactionCurrency is Erc20Token ? transactionCurrency.decimal : 18;
num amountToEVMChainMultiplier = pow(10, exponent);
String? contractAddress;
int estimatedGasUnitsForTransaction = 0;
int maxFeePerGasForTransaction = 0;
String toAddress = _credentials.outputs.first.isParsedAddress
? _credentials.outputs.first.extractedAddress!
: _credentials.outputs.first.address;
@ -367,14 +374,16 @@ abstract class EVMChainWalletBase
outputs.fold(0, (acc, value) => acc + (value.formattedCryptoAmount ?? 0)));
totalAmount = BigInt.from(totalOriginalAmount * amountToEVMChainMultiplier);
final estimateFees = await calculateActualEstimatedFeeForCreateTransaction(
final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction(
amount: totalAmount,
receivingAddressHex: toAddress,
priority: _credentials.priority!,
contractAddress: contractAddress,
);
estimatedFeesForTransaction = BigInt.from(estimateFees);
estimatedFeesForTransaction = BigInt.from(gasFeesModel.estimatedGasFee);
estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits;
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
if (erc20Balance.balance < totalAmount) {
throw EVMChainTransactionCreationException(transactionCurrency);
@ -392,14 +401,16 @@ abstract class EVMChainWalletBase
totalAmount = erc20Balance.balance;
}
final estimateFees = await calculateActualEstimatedFeeForCreateTransaction(
final gasFeesModel = await calculateActualEstimatedFeeForCreateTransaction(
amount: totalAmount,
receivingAddressHex: toAddress,
priority: _credentials.priority!,
contractAddress: contractAddress,
);
estimatedFeesForTransaction = BigInt.from(estimateFees);
estimatedFeesForTransaction = BigInt.from(gasFeesModel.estimatedGasFee);
estimatedGasUnitsForTransaction = gasFeesModel.estimatedGasUnits;
maxFeePerGasForTransaction = gasFeesModel.maxFeePerGas;
if (output.sendAll && transactionCurrency is! Erc20Token) {
totalAmount = (erc20Balance.balance - estimatedFeesForTransaction);
@ -420,12 +431,14 @@ abstract class EVMChainWalletBase
}
final pendingEVMChainTransaction = await _client.signTransaction(
estimatedGasUnits: estimatedGasUnitsForTransaction,
privateKey: _evmChainPrivateKey,
toAddress: toAddress,
amount: totalAmount,
gas: estimatedFeesForTransaction,
gasFee: estimatedFeesForTransaction,
priority: _credentials.priority!,
currency: transactionCurrency,
maxFeePerGas: maxFeePerGasForTransaction,
exponent: exponent,
contractAddress:
transactionCurrency is Erc20Token ? transactionCurrency.contractAddress : null,
@ -728,3 +741,25 @@ abstract class EVMChainWalletBase
@override
final String? passphrase;
}
class GasParamsHandler {
final int estimatedGasUnits;
final int estimatedGasFee;
final int maxFeePerGas;
final int gasPrice;
GasParamsHandler(
{required this.estimatedGasUnits,
required this.estimatedGasFee,
required this.maxFeePerGas,
required this.gasPrice});
static GasParamsHandler zero() {
return GasParamsHandler(
estimatedGasUnits: 0,
estimatedGasFee: 0,
maxFeePerGas: 0,
gasPrice: 0,
);
}
}