Skip to content

Commit f9a0cd6

Browse files
committed
feat: transaction notifications for incoming transactions
closes #300
1 parent a156253 commit f9a0cd6

1 file changed

Lines changed: 59 additions & 0 deletions

File tree

lib/wallets/wallet/wallet.dart

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import 'package:mutex/mutex.dart';
66

77
import '../../db/isar/main_db.dart';
88
import '../../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';
911
import '../../models/isar/models/ethereum/eth_contract.dart';
1012
import '../../models/keys/view_only_wallet_data.dart';
1113
import '../../models/node_model.dart';
@@ -15,6 +17,8 @@ import '../../services/event_bus/events/global/refresh_percent_changed_event.dar
1517
import '../../services/event_bus/events/global/wallet_sync_status_changed_event.dart';
1618
import '../../services/event_bus/global_event_bus.dart';
1719
import '../../services/node_service.dart';
20+
import '../../services/transaction_notification_tracker.dart';
21+
import '../../widgets/crypto_notifications.dart';
1822
import '../../utilities/amount/amount.dart';
1923
import '../../utilities/constants.dart';
2024
import '../../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

Comments
 (0)