fix: Already Known Error (#2606)

* fix: Already made error and update transactions two seconds after successful send for evm, tron and sol

* feat: Add updateTransactionsHistory method on WalletBase to handle transaction update immediately after sending

* Update lib/view_model/send/send_view_model.dart [skip ci]

---------

Co-authored-by: Omar Hatem <omarh.ismail1@gmail.com>
This commit is contained in:
David Adegoke
2025-10-25 13:34:29 +02:00
committed by GitHub
co-authored by Omar Hatem
parent 6388ae8af8
commit b0b053a19d
5 changed files with 80 additions and 44 deletions
+52 -38
View File
@@ -139,8 +139,7 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
bool get isMwebEnabled => balanceViewModel.mwebEnabled;
bool get isEVMWallet => walletType == WalletType.ethereum || walletType == WalletType.polygon ||
walletType == WalletType.base;
bool get isEVMWallet => isEVMCompatibleChain(walletType);
@action
void setShowAddressBookPopup(bool value) {
@@ -514,7 +513,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
});
}
// Swaps.xyz (EVM) path
if (isEVMWallet && trade != null && provider is SwapsXyzExchangeProvider) {
@@ -524,7 +522,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
BigInt.tryParse((trade.routerValue ?? '0').toString()) ?? BigInt.zero;
if (routerTo?.isNotEmpty == true && routerData?.isNotEmpty == true) {
// detect prepared ERC-20 transfer(...) (alt-vm deposit pattern)
String _selector(String s) =>
(s.startsWith('0x') && s.length >= 10) ? s.substring(0, 10) : '';
@@ -538,11 +535,13 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
// Optionally prebuild approval (SKIP for prepared transfer)
final tokenContract = trade.sourceTokenAddress ?? '';
final requiredAmount = BigInt.tryParse(
(trade.sourceTokenAmountRaw ?? '0').replaceAll('n', ''),
) ?? BigInt.zero;
(trade.sourceTokenAmountRaw ?? '0').replaceAll('n', ''),
) ??
BigInt.zero;
// Only do approval when NOT a prepared transfer, and only if the API hinted we might need it
final requiresTokenApproval = (trade.requiresTokenApproval ?? false) && !_isPreparedTransfer;
final requiresTokenApproval =
(trade.requiresTokenApproval ?? false) && !_isPreparedTransfer;
if (requiresTokenApproval && tokenContract.isNotEmpty && requiredAmount > BigInt.zero) {
if (walletType == WalletType.ethereum) {
@@ -656,7 +655,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
}
}
// Regular flow
pendingTransaction = await wallet.createTransaction(_credentials(provider));
@@ -772,21 +770,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
return; // skip the regular flow below
}
// Regular flow (non-Swaps)
if (pendingTransaction!.shouldCommitUR()) {
final urstr = await pendingTransaction!.commitUR();
final result = await Navigator.of(context).pushNamed(
Routes.urqrAnimatedPage,
arguments: urstr,
);
if (result == null) {
state = FailureState("Canceled by user");
return;
}
} else {
await pendingTransaction!.commit();
}
String address = outputs.fold('', (acc, value) {
return value.isParsedAddress
? '$acc${value.address}\n${value.extractedAddress}\n\n'
@@ -818,6 +801,17 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
nano!.updateTransactions(wallet);
}
// Immediate transaction update for EVM chains, Solana, and Tron
if (isEVMWallet || walletType == WalletType.solana || walletType == WalletType.tron) {
Future.delayed(Duration(seconds: 4), () async {
try {
await wallet.updateTransactionsHistory();
} catch (e) {
printV('Failed to update transactions after send: $e');
}
});
}
if (pendingTransaction!.id.isNotEmpty) {
TransactionInfo? tx;
if (walletType == WalletType.monero) {
@@ -1124,7 +1118,6 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
required BigInt requiredAmount,
int? sourceTokenDecimals,
}) async {
// Only EVM chains support ERC20 approvals
if (!isEVMWallet) return null;
@@ -1138,15 +1131,24 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
bool needsApproval = false;
if (walletType == WalletType.ethereum) {
needsApproval = await ethereum!.isApprovalRequired(
wallet, tokenContract, spender, requiredAmount,
wallet,
tokenContract,
spender,
requiredAmount,
);
} else if (walletType == WalletType.polygon) {
needsApproval = await polygon!.isApprovalRequired(
wallet, tokenContract, spender, requiredAmount,
wallet,
tokenContract,
spender,
requiredAmount,
);
} else if (walletType == WalletType.base) {
needsApproval = await base!.isApprovalRequired(
wallet, tokenContract, spender, requiredAmount,
wallet,
tokenContract,
spender,
requiredAmount,
);
}
@@ -1154,29 +1156,41 @@ abstract class SendViewModelBase extends WalletChangeListenerViewModel with Stor
final erc20Token = wallet.balance.keys.whereType<Erc20Token>().firstWhere(
(t) => t.contractAddress.toLowerCase() == tokenLc,
orElse: () => Erc20Token(
name: '',
symbol: '',
contractAddress: tokenContract,
decimal: sourceTokenDecimals ?? 18,
enabled: true,
),
);
orElse: () => Erc20Token(
name: '',
symbol: '',
contractAddress: tokenContract,
decimal: sourceTokenDecimals ?? 18,
enabled: true,
),
);
if (walletType == WalletType.ethereum) {
final priority = _settingsStore.priority[WalletType.ethereum]!;
return await ethereum!.createTokenApproval(
wallet, requiredAmount, spender, erc20Token, priority,
wallet,
requiredAmount,
spender,
erc20Token,
priority,
);
} else if (walletType == WalletType.polygon) {
final priority = _settingsStore.priority[WalletType.polygon]!;
return await polygon!.createTokenApproval(
wallet, requiredAmount, spender, erc20Token, priority,
wallet,
requiredAmount,
spender,
erc20Token,
priority,
);
} else if (walletType == WalletType.base) {
final priority = _settingsStore.priority[WalletType.base]!;
return await base!.createTokenApproval(
wallet, requiredAmount, spender, erc20Token, priority,
wallet,
requiredAmount,
spender,
erc20Token,
priority,
);
}