@@ -6,6 +6,8 @@ import 'package:mutex/mutex.dart';
66
77import '../../db/isar/main_db.dart' ;
88import '../../models/isar/models/blockchain_data/address.dart' ;
9+ import '../../models/isar/models/blockchain_data/transaction.dart' ;
10+ import '../../models/isar/models/blockchain_data/v2/transaction_v2.dart' ;
911import '../../models/isar/models/ethereum/eth_contract.dart' ;
1012import '../../models/keys/view_only_wallet_data.dart' ;
1113import '../../models/node_model.dart' ;
@@ -15,6 +17,8 @@ import '../../services/event_bus/events/global/refresh_percent_changed_event.dar
1517import '../../services/event_bus/events/global/wallet_sync_status_changed_event.dart' ;
1618import '../../services/event_bus/global_event_bus.dart' ;
1719import '../../services/node_service.dart' ;
20+ import '../../services/transaction_notification_tracker.dart' ;
21+ import '../../widgets/crypto_notifications.dart' ;
1822import '../../utilities/amount/amount.dart' ;
1923import '../../utilities/constants.dart' ;
2024import '../../utilities/enums/sync_type_enum.dart' ;
@@ -683,6 +687,14 @@ abstract class Wallet<T extends CryptoCurrency> {
683687 await (this as SparkInterface ).refreshSparkData ((0.3 , 0.6 ));
684688 }
685689
690+ // Capture known transaction IDs before updating so we can detect new ones.
691+ final knownTxids = await mainDB.isar.transactionV2s
692+ .where ()
693+ .walletIdEqualTo (walletId)
694+ .txidProperty ()
695+ .findAll ();
696+ final knownTxidSet = knownTxids.toSet ();
697+
686698 if (this is NamecoinWallet ) {
687699 await updateUTXOs ();
688700 _fireRefreshPercentChange (0.6 );
@@ -699,6 +711,53 @@ abstract class Wallet<T extends CryptoCurrency> {
699711 await fetchFuture;
700712 }
701713
714+ // Check for new incoming transactions and fire notification events.
715+ try {
716+ final tracker = TransactionNotificationTracker (walletId: walletId);
717+ final allTxs = await mainDB.isar.transactionV2s
718+ .where ()
719+ .walletIdEqualTo (walletId)
720+ .findAll ();
721+
722+ for (final tx in allTxs) {
723+ if (! knownTxidSet.contains (tx.txid) &&
724+ tx.type == TransactionType .incoming &&
725+ ! tracker.wasNotifiedPending (tx.txid)) {
726+ final amount = tx.getAmountReceivedInThisWallet (
727+ fractionDigits: cryptoCurrency.fractionDigits,
728+ );
729+
730+ CryptoNotificationsEventBus .instance.fire (
731+ CryptoNotificationEvent (
732+ title: "Incoming ${cryptoCurrency .prettyName } transaction" ,
733+ walletId: walletId,
734+ walletName: info.name,
735+ date: DateTime .fromMillisecondsSinceEpoch (
736+ tx.timestamp * 1000 ,
737+ ),
738+ shouldWatchForUpdates: tx.height == null || tx.height! <= 0 ,
739+ coin: cryptoCurrency,
740+ txid: tx.txid,
741+ confirmations: tx.getConfirmations (info.cachedChainHeight),
742+ requiredConfirmations:
743+ cryptoCurrency.minConfirms,
744+ payload: "${amount .decimal .toStringAsFixed (
745+ cryptoCurrency .fractionDigits ,
746+ )} ${cryptoCurrency .ticker }" ,
747+ ),
748+ );
749+
750+ await tracker.addNotifiedPending (tx.txid);
751+ }
752+ }
753+ } catch (e, s) {
754+ Logging .instance.w (
755+ "Transaction notification check failed: $e " ,
756+ error: e,
757+ stackTrace: s,
758+ );
759+ }
760+
702761 // TODO: [prio=low] handle this differently. Extra modification of this file for coin specific functionality should be avoided.
703762 if (! viewOnly && this is PaynymInterface && codesToCheck.isNotEmpty) {
704763 await (this as PaynymInterface ).checkForNotificationTransactionsTo (
0 commit comments