mirror of
https://github.com/cake-tech/cake_wallet.git
synced 2025-06-28 12:29:51 +00:00
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:
parent
ed600f9b8b
commit
9590aa25b6
40 changed files with 346 additions and 35 deletions
|
@ -36,7 +36,18 @@ abstract class EVMChainClient {
|
|||
|
||||
bool connect(Node node) {
|
||||
try {
|
||||
_client = Web3Client(node.uri.toString(), httpClient);
|
||||
Uri? rpcUri;
|
||||
bool isModifiedNodeUri = false;
|
||||
|
||||
if (node.uriRaw == 'eth.nownodes.io' || node.uriRaw == 'matic.nownodes.io') {
|
||||
isModifiedNodeUri = true;
|
||||
String nowNodeApiKey = secrets.nowNodesApiKey;
|
||||
|
||||
rpcUri = Uri.https(node.uriRaw, '/$nowNodeApiKey');
|
||||
}
|
||||
|
||||
_client =
|
||||
Web3Client(isModifiedNodeUri ? rpcUri!.toString() : node.uri.toString(), httpClient);
|
||||
|
||||
return true;
|
||||
} catch (e) {
|
||||
|
@ -83,23 +94,20 @@ abstract class EVMChainClient {
|
|||
}
|
||||
}
|
||||
|
||||
Future<int> getEstimatedGas({
|
||||
String? contractAddress,
|
||||
Future<int> getEstimatedGasUnitsForTransaction({
|
||||
required EthereumAddress toAddress,
|
||||
required EthereumAddress senderAddress,
|
||||
required EtherAmount value,
|
||||
String? contractAddress,
|
||||
EtherAmount? gasPrice,
|
||||
// EtherAmount? maxFeePerGas,
|
||||
// EtherAmount? maxPriorityFeePerGas,
|
||||
EtherAmount? maxFeePerGas,
|
||||
}) async {
|
||||
try {
|
||||
if (contractAddress == null) {
|
||||
final estimatedGas = await _client!.estimateGas(
|
||||
sender: senderAddress,
|
||||
gasPrice: gasPrice,
|
||||
to: toAddress,
|
||||
value: value,
|
||||
// maxPriorityFeePerGas: maxPriorityFeePerGas,
|
||||
// maxFeePerGas: maxFeePerGas,
|
||||
);
|
||||
|
||||
|
@ -133,7 +141,9 @@ abstract class EVMChainClient {
|
|||
required Credentials privateKey,
|
||||
required String toAddress,
|
||||
required BigInt amount,
|
||||
required BigInt gas,
|
||||
required BigInt gasFee,
|
||||
required int estimatedGasUnits,
|
||||
required int maxFeePerGas,
|
||||
required EVMChainTransactionPriority priority,
|
||||
required CryptoCurrency currency,
|
||||
required int exponent,
|
||||
|
@ -152,6 +162,8 @@ abstract class EVMChainClient {
|
|||
maxPriorityFeePerGas: EtherAmount.fromInt(EtherUnit.gwei, priority.tip),
|
||||
amount: isNativeToken ? EtherAmount.inWei(amount) : EtherAmount.zero(),
|
||||
data: data != null ? hexToBytes(data) : null,
|
||||
maxGas: estimatedGasUnits,
|
||||
maxFeePerGas: EtherAmount.fromInt(EtherUnit.wei, maxFeePerGas),
|
||||
);
|
||||
|
||||
Uint8List signedTransaction;
|
||||
|
@ -180,7 +192,7 @@ abstract class EVMChainClient {
|
|||
return PendingEVMChainTransaction(
|
||||
signedTransaction: signedTransaction,
|
||||
amount: amount.toString(),
|
||||
fee: gas,
|
||||
fee: gasFee,
|
||||
sendTransaction: _sendTransaction,
|
||||
exponent: exponent,
|
||||
);
|
||||
|
@ -191,7 +203,10 @@ abstract class EVMChainClient {
|
|||
required EthereumAddress to,
|
||||
required EtherAmount amount,
|
||||
EtherAmount? maxPriorityFeePerGas,
|
||||
EtherAmount? gasPrice,
|
||||
EtherAmount? maxFeePerGas,
|
||||
Uint8List? data,
|
||||
int? maxGas,
|
||||
}) {
|
||||
return Transaction(
|
||||
from: from,
|
||||
|
@ -199,6 +214,9 @@ abstract class EVMChainClient {
|
|||
maxPriorityFeePerGas: maxPriorityFeePerGas,
|
||||
value: amount,
|
||||
data: data,
|
||||
maxGas: maxGas,
|
||||
gasPrice: gasPrice,
|
||||
maxFeePerGas: maxFeePerGas,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue