mirror of
https://github.com/Such-Software/hash-wallet.git
synced 2026-10-17 05:41:29 +02:00
fix: walletconnect fee refresh (#3153)
* fix: refresh EIP-1559 fees before sign for walletconnect transactions * fix: add missing data to configure file --------- Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
co-authored by
Omar Hatem
parent
fd62cd5b52
commit
ef752c747e
+20
-6
@@ -239,10 +239,7 @@ class CWEVM extends EVM {
|
||||
(wallet as EVMChainWallet).isApprovalRequired(tokenContract, spender, requiredAmount);
|
||||
|
||||
@override
|
||||
Future<BigInt?> getAllowance(
|
||||
WalletBase wallet,
|
||||
String tokenContract,
|
||||
String spender) =>
|
||||
Future<BigInt?> getAllowance(WalletBase wallet, String tokenContract, String spender) =>
|
||||
(wallet as EVMChainWallet).getAllowance(tokenContract, spender);
|
||||
|
||||
@override
|
||||
@@ -272,7 +269,7 @@ class CWEVM extends EVM {
|
||||
String to,
|
||||
String dataHex,
|
||||
BigInt valueWei,
|
||||
TransactionPriority? priority,{
|
||||
TransactionPriority? priority, {
|
||||
bool useBlinkProtection = true,
|
||||
String? sourceTokenAddress,
|
||||
BigInt? sourceTokenAmount,
|
||||
@@ -481,7 +478,7 @@ class CWEVM extends EVM {
|
||||
|
||||
@override
|
||||
BigInt? getERC20AvailableBalance(Object balance) {
|
||||
if(balance is EVMChainERC20Balance) {
|
||||
if (balance is EVMChainERC20Balance) {
|
||||
return balance.balance;
|
||||
}
|
||||
return null;
|
||||
@@ -544,6 +541,23 @@ class CWEVM extends EVM {
|
||||
@override
|
||||
bool hasPriorityFee(int chainId) => EVMChainUtils.hasPriorityFee(chainId);
|
||||
|
||||
@override
|
||||
Future<EvmWalletConnectFeeQuote?> getWCBufferedFeeQuote(
|
||||
WalletBase wallet,
|
||||
TransactionPriority priority,
|
||||
) async {
|
||||
if (wallet is! EVMChainWallet) return null;
|
||||
|
||||
final data = await wallet.getWCBufferedFeeQuote(priority);
|
||||
if (data == null) return null;
|
||||
|
||||
return EvmWalletConnectFeeQuote(
|
||||
maxFeePerGasWei: data.maxFeePerGasWei,
|
||||
maxPriorityFeePerGasWei: data.maxPriorityFeePerGasWei,
|
||||
latestBaseFeeWei: data.latestBaseFeeWei,
|
||||
);
|
||||
}
|
||||
|
||||
Future<({double usdValue, bool hasValidFiatPrice})> _getTokenUsdValueAndFiatCheck(
|
||||
Erc20Token token,
|
||||
BigInt balanceWei,
|
||||
|
||||
@@ -432,43 +432,14 @@ class EvmChainServiceImpl {
|
||||
}
|
||||
}
|
||||
|
||||
// we need to check if dApp provides the gas values and if not, we need to estimate them
|
||||
final hasGasLimit = transaction.maxGas != null && transaction.maxGas! > 0;
|
||||
final hasGasPrice = transaction.gasPrice != null;
|
||||
final hasMaxFeePerGas = transaction.maxFeePerGas != null;
|
||||
final hasMaxPriorityFeePerGas = transaction.maxPriorityFeePerGas != null;
|
||||
|
||||
final needsGasEstimation = !hasGasLimit || (!hasGasPrice && !hasMaxFeePerGas);
|
||||
|
||||
if (needsGasEstimation) {
|
||||
try {
|
||||
final gasPrice = hasGasPrice ? transaction.gasPrice! : await ethClient.getGasPrice();
|
||||
|
||||
if (!hasGasLimit) {
|
||||
final gasLimit = await ethClient.estimateGas(
|
||||
sender: transaction.from,
|
||||
to: transaction.to,
|
||||
value: transaction.value,
|
||||
data: transaction.data,
|
||||
gasPrice: gasPrice,
|
||||
);
|
||||
|
||||
if (hasMaxFeePerGas || hasMaxPriorityFeePerGas) {
|
||||
transaction = transaction.copyWith(maxGas: gasLimit.toInt());
|
||||
} else {
|
||||
transaction = transaction.copyWith(
|
||||
gasPrice: hasGasPrice ? transaction.gasPrice : gasPrice,
|
||||
maxGas: gasLimit.toInt(),
|
||||
);
|
||||
}
|
||||
} else if (!hasGasPrice && !hasMaxFeePerGas) {
|
||||
transaction = transaction.copyWith(gasPrice: gasPrice);
|
||||
}
|
||||
} on RPCError catch (e) {
|
||||
return JsonRpcError(code: e.errorCode, message: e.message);
|
||||
}
|
||||
try {
|
||||
transaction = await _ensureWCTransactionHasGasLimit(transaction);
|
||||
} on RPCError catch (e) {
|
||||
return JsonRpcError(code: e.errorCode, message: e.message);
|
||||
}
|
||||
|
||||
transaction = await _applyWCBufferedFees(transaction);
|
||||
|
||||
final gweiGasPrice =
|
||||
(transaction.gasPrice?.getInWei ?? transaction.maxFeePerGas?.getInWei ?? BigInt.zero) /
|
||||
BigInt.from(1000000000);
|
||||
@@ -500,6 +471,90 @@ class EvmChainServiceImpl {
|
||||
return JsonRpcError(code: 5002, message: S.current.user_rejected_method);
|
||||
}
|
||||
|
||||
Future<Transaction> _ensureWCTransactionHasGasLimit(Transaction transaction) async {
|
||||
final hasGasLimit = transaction.maxGas != null && transaction.maxGas! > 0;
|
||||
if (hasGasLimit) return transaction;
|
||||
|
||||
final hint = transaction.gasPrice ?? transaction.maxFeePerGas ?? await ethClient.getGasPrice();
|
||||
|
||||
final gasLimit = await ethClient.estimateGas(
|
||||
sender: transaction.from,
|
||||
to: transaction.to,
|
||||
value: transaction.value,
|
||||
data: transaction.data,
|
||||
gasPrice: hint,
|
||||
);
|
||||
|
||||
if (transaction.isEIP1559) {
|
||||
return transaction.copyWith(maxGas: gasLimit.toInt());
|
||||
}
|
||||
|
||||
return transaction.copyWith(
|
||||
maxGas: gasLimit.toInt(),
|
||||
gasPrice: transaction.gasPrice ?? hint,
|
||||
);
|
||||
}
|
||||
|
||||
Future<Transaction> _applyWCBufferedFees(Transaction transaction) async {
|
||||
try {
|
||||
final storedPriority =
|
||||
appStore.settingsStore.getPriority(appStore.wallet!.type, chainId: reference.chainId);
|
||||
final priority = storedPriority ?? evm!.getDefaultTransactionPriority();
|
||||
|
||||
final quote = await evm!.getWCBufferedFeeQuote(appStore.wallet!, priority);
|
||||
if (quote != null) {
|
||||
return _mergeWCBufferedFees(transaction, quote);
|
||||
}
|
||||
} catch (e) {
|
||||
debugPrint('WalletConnect fee refresh failed: $e');
|
||||
}
|
||||
|
||||
if (!transaction.isEIP1559 && transaction.gasPrice == null) {
|
||||
return transaction.copyWith(gasPrice: await ethClient.getGasPrice());
|
||||
}
|
||||
|
||||
return transaction;
|
||||
}
|
||||
|
||||
Transaction _mergeWCBufferedFees(Transaction transaction, EvmWalletConnectFeeQuote quote) {
|
||||
if (transaction.isEIP1559) {
|
||||
// the fees coming from the dApp
|
||||
final dAppMax = transaction.maxFeePerGas?.getInWei ?? BigInt.zero;
|
||||
final dAppPri = transaction.maxPriorityFeePerGas?.getInWei ?? BigInt.zero;
|
||||
|
||||
// the updated fees coming from the wallet, handles buffered fees
|
||||
final quoteMax = BigInt.from(quote.maxFeePerGasWei);
|
||||
final quotePri = BigInt.from(quote.maxPriorityFeePerGasWei);
|
||||
|
||||
// we'll just use the higher of the two
|
||||
var newMaxFeePerGasWei = dAppMax > quoteMax ? dAppMax : quoteMax;
|
||||
var newPriorityFeePerGasWei = dAppPri > quotePri ? dAppPri : quotePri;
|
||||
|
||||
final base = quote.latestBaseFeeWei;
|
||||
if (base != null) {
|
||||
final baseB = BigInt.from(base);
|
||||
final maxPriAllowed = newMaxFeePerGasWei - baseB;
|
||||
if (newPriorityFeePerGasWei > maxPriAllowed) {
|
||||
if (maxPriAllowed > BigInt.zero) {
|
||||
newPriorityFeePerGasWei = maxPriAllowed;
|
||||
} else {
|
||||
newMaxFeePerGasWei = baseB + newPriorityFeePerGasWei;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return transaction.copyWith(
|
||||
maxFeePerGas: EtherAmount.inWei(newMaxFeePerGasWei),
|
||||
maxPriorityFeePerGas: EtherAmount.inWei(newPriorityFeePerGasWei),
|
||||
);
|
||||
}
|
||||
|
||||
final dPrice = transaction.gasPrice?.getInWei ?? BigInt.zero;
|
||||
final floor = BigInt.from(quote.maxFeePerGasWei);
|
||||
final newPriceWei = dPrice > floor ? dPrice : floor;
|
||||
return transaction.copyWith(gasPrice: EtherAmount.inWei(newPriceWei));
|
||||
}
|
||||
|
||||
void _onSessionRequest(SessionRequestEvent? args) async {
|
||||
if (args != null && args.chainId == getChainId()) {
|
||||
debugPrint('_onSessionRequest ${args.toString()}');
|
||||
|
||||
Reference in New Issue
Block a user