fix tx status update (#3123)
What changed, and why it matters
This commit fixes how the Cake Wallet app updates and displays transaction statuses. It prevents duplicate transactions from appearing in the history list, ensures pending/completed transactions are correctly distinguished, and fixes a small UI issue on the receive screen when automatic address rotation is turned off. There is no direct evidence this is a security vulnerability, but stale or incorrect transaction status could mislead users about whether a payment was confirmed.
Treat as a routine bug-fix commit. Users relying on transaction status for high-value decisions should verify on-chain confirmation independently until the fix is released. No urgent security response is indicated by the diff alone.
Security signals we found
UI state inconsistency between transaction list and actual confirmation status
Duplicate transaction entries could obscure true transaction state
No cryptographic, authentication, or input-validation changes observed
Evidence from the diff
The patch modifies four Dart files. In dashboard_view_model.dart it removes old transaction entries that match a newly fetched transaction by both txHash and direction before adding the updated entries, preventing stale duplicates. In transaction_list_item.dart it expands the equality operator to consider confirmations, pending state, and direction, so ObservableList updates reflect status changes. In history_section.dart it adjusts the empty-state widget so the ‘transactions will appear here’ message is hidden while syncing. In receive_info_box.dart it returns null for the auto-address info box when AutoGenerateSubaddressStatus is disabled, avoiding a misleading UI element.
Changed components
lib/view_model/dashboard/dashboard_view_model.dartlib/view_model/dashboard/transaction_list_item.dartlib/new-ui/widgets/coins_page/assets_history/history_section.dartlib/new-ui/widgets/receive_page/receive_info_box.dartInspect captured patch +12 / −4
diff --git a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
index 82109190..aa6672fd 100644
--- a/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
+++ b/lib/new-ui/widgets/coins_page/assets_history/history_section.dart
@@ -30,12 +30,11 @@ class HistorySection extends StatelessWidget {
return SliverPadding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
sliver: Observer(
- builder: (_) => (dashboardViewModel.items.isEmpty &&
- dashboardViewModel.status is! SyncingSyncStatus)
+ builder: (_) => (dashboardViewModel.items.isEmpty)
? SliverPadding(
padding: EdgeInsets.only(top: 24),
sliver: SliverToBoxAdapter(
- child: Center(
+ child: (dashboardViewModel.status is SyncingSyncStatus) ? SizedBox.shrink() : Center(
child: Text(S.of(context).transactions_will_appear_here,
style: TextStyle(
fontSize: 14,
diff --git a/lib/new-ui/widgets/receive_page/receive_info_box.dart b/lib/new-ui/widgets/receive_page/receive_info_box.dart
index f99a8f0c..9b6b65df 100644
--- a/lib/new-ui/widgets/receive_page/receive_info_box.dart
+++ b/lib/new-ui/widgets/receive_page/receive_info_box.dart
@@ -30,6 +30,8 @@ class ReceiveInfoBox extends StatelessWidget {
onDismissed: onDismissed,
);
default:
+ if(autoGenerateSubaddressStatus == AutoGenerateSubaddressStatus.disabled)
+ return null;
return ReceiveInfoBox(
iconPath: "assets/new-ui/info.svg",
message: S.current.infobox_auto_address,
diff --git a/lib/view_model/dashboard/dashboard_view_model.dart b/lib/view_model/dashboard/dashboard_view_model.dart
index 2a699e38..3dbc0eaf 100644
--- a/lib/view_model/dashboard/dashboard_view_model.dart
+++ b/lib/view_model/dashboard/dashboard_view_model.dart
@@ -490,6 +490,10 @@ abstract class DashboardViewModelBase with Store {
))
.where((item) => !transactions.contains(item));
+ transactions.removeWhere((item) =>
+ newTransactions.any((tx) => tx.transaction.txHash == item.transaction.txHash && tx.transaction.direction == item.transaction.direction)
+ );
+
transactions.addAll(newTransactions);
// transactions.clear();
// transactions.addAll(relevantTxs.map((tx) => TransactionListItem(
diff --git a/lib/view_model/dashboard/transaction_list_item.dart b/lib/view_model/dashboard/transaction_list_item.dart
index de025e11..1fb3f304 100644
--- a/lib/view_model/dashboard/transaction_list_item.dart
+++ b/lib/view_model/dashboard/transaction_list_item.dart
@@ -293,7 +293,10 @@ class TransactionListItem extends ActionListItem with Keyable {
@override
bool operator ==(Object other) {
if (other is TransactionListItem) {
- return other.transaction.txHash == transaction.txHash;
+ return other.transaction.txHash == transaction.txHash &&
+ other.transaction.confirmations == transaction.confirmations &&
+ other.transaction.isPending == transaction.isPending &&
+ other.transaction.direction == transaction.direction;
}
return false;
}
Why this scored 23/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.