fix: stop estimating the desktop fee for a zero amount
What changed, and why it matters
This commit fixes a UI bug in the desktop version of Stack Wallet where the send amount could be lost while the app was trying to estimate transaction fees. The fix keeps the amount 'alive' in memory so fee estimation does not accidentally reset it to zero. There is no direct evidence this is a security vulnerability, but it could cause user confusion or failed transactions.
Treat as a routine bug fix. No immediate security action required. If the amount-reset behavior could cause users to send incorrect amounts, consider a broader review of provider lifecycle around transaction forms.
Security signals we found
State lifecycle issue in UI provider could lead to loss of user input
Fix prevents fee estimation from silently resetting send amount to zero
No cryptographic, authentication, or network security changes present
Evidence from the diff
The change adds a ref.listen(sendAmountProvider, (_, __) {}) call in the DesktopSendFeeForm widget. In Riverpod, providers are auto-disposed when no listeners/watchers exist. Previously, the send amount provider may have been disposed during the fee-estimation flow, causing the amount to be lost or reset. By listening to it, the provider stays alive. A test verifies the amount is preserved when one fee fetch fails and the widget rebuilds.
Changed components
lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.darttest/pages_desktop_specific/wallet/desktop_send_fee_form_test.dartInspect captured patch +22 / −0
### lib/pages_desktop_specific/my_stack_view/wallet_view/sub_widgets/desktop_send_fee_form.dart
@@ -108,6 +108,8 @@ class _DesktopSendFeeFormState extends ConsumerState<DesktopSendFeeForm> {
@override
Widget build(BuildContext context) {
+ // Keep the send amount alive for the fee estimates.
+ ref.listen(sendAmountProvider, (_, __) {});
final isCustomFee = ref.watch(feeRateTypeDesktopStateProvider).isCustom;
final locale = ref.watch(
localeServiceChangeNotifierProvider.select((value) => value.locale),
### test/pages_desktop_specific/wallet/desktop_send_fee_form_test.dart
@@ -141,4 +141,24 @@ void main() {
expect(wallet.feeFetches, 2);
expect(find.byType(DesktopFeeItem), findsOneWidget);
});
+
+ testWidgets("the amount is kept while no fee estimate is shown", (
+ tester,
+ ) async {
+ final wallet = _FeeWallet(failingFetches: 1);
+ final rebuild = await _pumpForm(tester, wallet);
+ final container = ProviderScope.containerOf(
+ tester.element(find.byType(DesktopSendFeeForm)),
+ );
+ final amount = Amount(rawValue: BigInt.from(22000), fractionDigits: 8);
+ container.read(sendAmountProvider.notifier).state = amount;
+ await tester.pump();
+
+ rebuild(() {});
+ await tester.pump();
+ await tester.pump();
+
+ expect(find.byType(DesktopFeeItem), findsOneWidget);
+ expect(container.read(sendAmountProvider), amount);
+ });
}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.