Skip to content

Conversation

@BraCR10
Copy link
Contributor

@BraCR10 BraCR10 commented Nov 10, 2025

Restore Feature Implementation

This PR introduces the restore feature to regenerate order states.
Below are the key details and implementation notes:


1. Main Logic

The core logic for the restore process is located in
mobile/lib/features/restore/restore_manager.dart.

The method initRestoreProcess() can be triggered in three different ways:

  • When importing a new mnemonic from
    mobile/lib/features/key_manager/key_management_screen.dart
  • When changing the Mostro public key
  • When refreshing using the new button:
    image

2. Clearing Current State

Before starting the restore process, the current state is cleared to ensure consistency:
image


3. Blocking Old Events During Restore

A new flag was added in
mobile/lib/features/order/notifiers/abstract_mostro_notifier.dart
to block processing of old incoming events during the restoration process.
This prevents outdated data from interfering with the new restored state.

image
image


4. Restore Delay

An 8-second delay is introduced before updating the order state with the data received from Mostro’s restore responses.
This delay helps avoid overwriting the restored state with old events that may still be arriving during subscription setup.

image


5. TODO: Dispute Creator Determination

There’s a pending TODO in _determineIfUserInitiatedDispute since it’s still unclear how to determine the dispute creator with the current information provided by Mostro during restoration events.

image


6. Mostro Message Updates

Minor updates were made to
mobile/lib/data/models/mostro_message.dart
to support restore request messages, in addition to the existing order messages.

image


7. Mnemonic Validation Utility

A new file was created:
mobile/lib/shared/utils/mnemonic_validator.dart
This handles mnemonic word validation to ensure input accuracy before triggering restore operations.

image


Feedback

If you have any feedback or suggestions for improvement, please let me know. 🙏

Summary by CodeRabbit

  • New Features

    • Import accounts via a mnemonic dialog with validation and a new "Refresh User" button to trigger a multi-stage restore flow.
    • Visual restore overlay and progress UI showing step-by-step status, progress counts, completion and error states.
    • Support for fetching detailed orders and trade index during restore, improving orders handling.
  • Bug Fixes

    • Suppress live message processing during restore and ignore historical restore events to prevent inconsistent updates.
  • Documentation

    • Added/updated localization strings for import, refresh, and restore UI flows.

Protocol Compliance 
  - Update MostroMessage serialization to use correct wrapper key:
    * "restore" key for Action.restore messages
    * "order" key for all other actions (backward compatible)
  - Implement EmptyPayload class for null payload serialization
  - Support full privacy mode in restore requests:
    * Reputation mode: includes master key signature
    * Full privacy mode: omits master key, uses only trade key
 ## Restore Session Flow
  - Implement RestoreService with initial session restore workflow:
    1. Clear existing data (sessions, storage, notifications)
    2. Create temporary subscription on trade key index 1
    3. Send restore-session request to Mostro
    4. Handle restore response with orders and disputes data
 - Add RestoreOverlay widget with multi-stage progress indicator
  - Add ImportMnemonicDialog for mnemonic phrase input and validation
  - Implement RestoreProgressNotifier for state management
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Nov 10, 2025

Walkthrough

Adds a multi-stage restore workflow: new payload types/models, restore orchestration and progress state/providers, a visible restore overlay, mnemonic import UI and validator, message filtering and restore-mode gating, small repo/test adjustments, settings integration, and localized strings.

Changes

Cohort / File(s) Summary
Core App Integration
lib/core/app.dart
Wraps the router builder with RestoreOverlay so the overlay is rendered above routed content.
Payload & Message Models
lib/data/models/enums/action.dart, lib/data/models/mostro_message.dart, lib/data/models/payload.dart, lib/data/models/last_trade_index_response.dart, lib/data/models/orders_request.dart, lib/data/models/orders_response.dart, lib/data/models/restore_response.dart
Adds restore, orders, lastTradeIndex actions; adds EmptyPayload, OrdersPayload, OrdersResponse/OrderDetail, LastTradeIndexResponse, RestoreData/RestoredOrder/RestoredDispute; updates MostroMessage parsing/serialization/signing to handle restore wrapper keys and empty payloads.
Restore Service & State
lib/features/restore/restore_manager.dart, lib/features/restore/restore_progress_state.dart, lib/features/restore/restore_progress_notifier.dart, lib/features/restore/restore_mode_provider.dart
Adds RestoreService (multi-stage restore), RestoreStep/RestoreProgressState, RestoreProgressNotifier + provider, and isRestoringProvider to gate message processing.
Restore UI
lib/features/restore/restore_overlay.dart
New RestoreOverlay ConsumerWidget that displays restore progress/status (responsive layout, icons, localized messages).
Key Management UI
lib/features/key_manager/import_mnemonic_dialog.dart, lib/features/key_manager/key_management_screen.dart
Adds ImportMnemonicDialog with BIP39 validation; key management screen adds Import and Refresh flows and triggers restore and notification-clear actions.
Order Notifiers & Flow Control
lib/features/order/notfiers/abstract_mostro_notifier.dart, lib/features/order/notfiers/order_notifier.dart
Adds restore-mode early-skip (reads isRestoringProvider) to incoming message handling; OrderNotifier gains updateStateFromMessage and updateDispute for restore usage.
Services Filtering
lib/services/mostro_service.dart
Adds _isRestorePayload helper and skips historical restore-related payloads; validates decrypted payload structure before processing.
Repositories & Tests
lib/data/repositories/open_orders_repository.dart, test/mocks.mocks.dart
Adds clearCache() to OpenOrdersRepository; updates mocks to include clearCache, updateStateFromMessage, and updateDispute.
Notifications Integration
lib/features/notifications/utils/notification_message_mapper.dart, lib/features/notifications/widgets/notification_item.dart
Extends mapper and tap-handling with restore, orders, lastTradeIndex cases (placeholder localization keys and no-op tap behavior).
Settings Integration
lib/features/settings/settings_screen.dart
Triggers a restore attempt when the Mostro public key is changed (fires restoreService after successful update).
Utilities
lib/shared/utils/mnemonic_validator.dart
Adds validateMnemonic(String) using package:bip39 to validate BIP39 mnemonics.
Localization
lib/l10n/intl_en.arb, lib/l10n/intl_es.arb, lib/l10n/intl_it.arb
Adds/updates strings for import/refresh dialogs, mnemonic validation, restore overlay steps, and refresh flow across languages; updates importMostroUser label values.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor User
    participant KeyScreen as Key Management Screen
    participant Dialog as ImportMnemonicDialog
    participant RestoreSvc as RestoreService
    participant Progress as RestoreProgressNotifier
    participant Overlay as RestoreOverlay
    participant Relay as Relay/Mostro

    User->>KeyScreen: Tap Import
    KeyScreen->>Dialog: showDialog(...)
    Dialog->>Dialog: validateMnemonic (BIP39)
    Dialog-->>KeyScreen: return mnemonic
    KeyScreen->>RestoreSvc: importMnemonicAndRestore(mnemonic)
    RestoreSvc->>Progress: startRestore()
    Progress->>Overlay: set visible (requesting)

    RestoreSvc->>Relay: send Action.restore (wrapper: "restore")
    Relay-->>RestoreSvc: restore_data (orders & disputes)
    RestoreSvc->>Progress: updateStep(receivingOrders)
    RestoreSvc->>Relay: send Action.orders (wrapper: "restore" / "orders")
    Relay-->>RestoreSvc: orders details
    RestoreSvc->>Progress: updateStep(loadingDetails)
    RestoreSvc->>Relay: send Action.lastTradeIndex
    Relay-->>RestoreSvc: last-trade-index
    RestoreSvc->>Progress: updateStep(finalizing)
    RestoreSvc->>Progress: completeRestore()
    Progress->>Overlay: show(completed) then hide()
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Areas needing extra attention:

  • lib/features/restore/restore_manager.dart — complex async orchestration, timeouts, session/key handling, and state mutations.
  • lib/data/models/mostro_message.dart — wrapper selection and backward-compatible serialization/signing.
  • lib/features/order/notfiers/abstract_mostro_notifier.dart and lib/services/mostro_service.dart — message filtering, restore-mode gating, and edge cases for skipped messages.
  • Localization ARB files — ensure consistent placeholders and key usage across languages.
  • test/mocks.mocks.dart — updated mocks must match new method signatures used by tests.

Possibly related PRs

Suggested reviewers

  • grunch
  • Catrya

Poem

🐇 I nibble mnemonic seeds at night,
I hop through relays till orders are right,
I stitch disputes and indices anew,
An overlay counts each happy view,
Hooray — the user's data springs to light! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Restore orders feature' accurately describes the main change: implementing a comprehensive restore feature for regenerating order states, as confirmed by the PR objectives and extensive changes across restore-related files.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3c59a29 and cf3f61a.

📒 Files selected for processing (1)
  • lib/features/restore/restore_manager.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
lib/features/**

📄 CodeRabbit inference engine (AGENTS.md)

Place application feature code under lib/features//, grouped by domain

Files:

  • lib/features/restore/restore_manager.dart
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Use Dart formatter defaults (two-space indentation, trailing commas) and run flutter format before committing
Resolve all Flutter analyzer warnings (flutter analyze must be clean)

**/*.dart: Remove unused imports and unused dependencies
Do not add // ignore: must_be_immutable to classes within generated files; rely on regeneration and existing file-level ignores

Files:

  • lib/features/restore/restore_manager.dart
lib/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Name Riverpod providers as Provider or Notifier

lib/**/*.dart: Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text
Use clear, concise English for variable names, function names, and code comments; all comments must be in English
Target zero flutter analyze issues
Use latest Flutter/Dart APIs (e.g., Color.withValues() instead of withOpacity())
After async operations, check mounted before using BuildContext
Use const constructors where possible

Files:

  • lib/features/restore/restore_manager.dart
🧠 Learnings (6)
📓 Common learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/*.dart : Use clear, concise English for variable names, function names, and code comments; all comments must be in English

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: All changes should pass flutter analyze before commit and follow conventional commits; avoid AI references in commit messages

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Initialize Sembast database in shared/providers/mostro_database_provider.dart

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • lib/features/restore/restore_manager.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (8)
lib/features/restore/restore_manager.dart (8)

1-43: LGTM! Clean imports and clear enum definition.

The imports are well-organized and the RestoreStage enum clearly defines the three phases of the restore workflow.


45-88: LGTM! Solid initialization and cleanup logic.

The class structure is well-organized with proper field declarations. The importMnemonicAndRestore method correctly invalidates and reinitializes the key manager provider after import, and _clearAll provides comprehensive cleanup with appropriate error handling.


90-141: LGTM! Robust event handling and subscription management.

The timeout handling in _waitForEvent, the safe completion checks in _handleTempSubscriptionsResponse, and the proper filter configuration in _createTempSubscription (including limit: 0 for new events only) demonstrate solid async event management.


143-167: LGTM! Request methods follow consistent pattern.

Both _sendRestoreRequest and _sendOrdersDetailsRequest properly validate key initialization, respect privacy mode settings, and construct Mostro messages correctly.

Also applies to: 231-255


360-450: LGTM! Comprehensive dispute and status handling.

Both _determineIfUserInitiatedDispute and _getActionFromStatus are well-implemented. The dispute determination includes proper security verification and safe fallbacks. The TODO comment on Line 398 appropriately acknowledges the known limitation with the current protocol approach.


452-627: LGTM! Robust restore processing with excellent error handling.

The restore method handles the complex multi-order restoration well:

  • Proper enable/disable of restore mode flag with cleanup in catch block (lines 467-468, 618-619, 623)
  • Resilient error handling that continues processing remaining orders if one fails (lines 610-612)
  • Creates sessions, builds messages, and updates state correctly
  • The 8-second delay (line 514) is well-documented with a WARNING comment explaining the relay behavior rationale

629-736: LGTM! Excellent orchestration and cleanup.

The initRestoreProcess method expertly orchestrates the multi-stage restore workflow:

  • Proper validation of master key and Mostro configuration
  • Handles the no-orders edge case gracefully (lines 677-686)
  • Strategic subscription cancellation before stage 4 to avoid interference (line 703)
  • Comprehensive cleanup in finally block ensuring resources are released (lines 722-734)
  • Conditional completion based on error state prevents premature success signals (lines 730-734)

739-741: LGTM! Provider follows naming conventions.

The restoreServiceProvider follows the coding guideline for Riverpod provider naming.

As per coding guidelines.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@BraCR10 BraCR10 changed the title Restore sessions feature Restore orders feature Nov 10, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 5

🧹 Nitpick comments (10)
lib/data/models/orders_request.dart (1)

11-15: Add defensive checks in fromJson for robustness.

The fromJson factory doesn't validate that the 'ids' key exists or that it's a List, which could cause runtime errors if the JSON is malformed or unexpected.

Apply this diff to add defensive checks:

 factory OrdersPayload.fromJson(Map<String, dynamic> json) {
+  final idsList = json['ids'];
+  if (idsList == null) {
+    return const OrdersPayload(ids: []);
+  }
+  if (idsList is! List) {
+    throw FormatException('Expected List for "ids" but got ${idsList.runtimeType}');
+  }
   return OrdersPayload(
-    ids: (json['ids'] as List<dynamic>).map((e) => e as String).toList(),
+    ids: idsList.map((e) => e as String).toList(),
   );
 }
lib/features/restore/restore_progress_state.dart (1)

42-45: Consider adding bounds checking to progressPercentage.

The progressPercentage getter doesn't validate that currentProgress is within [0, totalProgress], which could return values outside the expected [0.0, 1.0] range if the state is updated incorrectly.

Apply this diff to ensure the percentage stays within bounds:

 double get progressPercentage {
   if (totalProgress == 0) return 0.0;
-  return currentProgress / totalProgress;
+  final percentage = currentProgress / totalProgress;
+  return percentage.clamp(0.0, 1.0);
 }
lib/services/mostro_service.dart (1)

44-45: Clarify comment about trade index 1.

The comment states "The app always use trade index 1 for restore-related messages" but this invariant isn't enforced in code. Consider:

  1. If this is a critical assumption, add validation that rejects messages with other trade indices
  2. If this is merely informational, clarify that this is a convention, not an enforced rule
  3. Add a reference to where trade index 1 is assigned for restore sessions
lib/data/models/mostro_message.dart (1)

101-111: Consider extracting wrapper key selection logic.

The wrapper key selection logic (action == Action.restore || action == Action.lastTradeIndex ? 'restore' : 'order') is duplicated in both sign() (line 103) and serialize() (line 115). Consider extracting to a helper:

String _getWrapperKey() {
  return (action == Action.restore || action == Action.lastTradeIndex) 
      ? 'restore' 
      : 'order';
}

Then use in both methods to ensure consistency and simplify future maintenance.

lib/data/models/orders_response.dart (2)

12-19: Consider simplifying nullable list handling.

The nullable list handling is correct but could be more concise.

Apply this diff for a more idiomatic pattern:

   factory OrdersResponse.fromJson(Map<String, dynamic> json) {
     return OrdersResponse(
-      orders: (json['orders'] as List<dynamic>?)
-              ?.map((o) => OrderDetail.fromJson(o as Map<String, dynamic>))
-              .toList() ??
-          [],
+      orders: (json['orders'] as List<dynamic>? ?? [])
+          .map((o) => OrderDetail.fromJson(o as Map<String, dynamic>))
+          .toList(),
     );
   }

60-77: Simplify nullable field parsing.

The nullable field handling is overly verbose. Dart's type system can handle this more elegantly.

Apply this diff to simplify the factory:

   factory OrderDetail.fromJson(Map<String, dynamic> json) {
     return OrderDetail(
       id: json['id'] as String,
       kind: json['kind'] as String,
       status: json['status'] as String,
       amount: json['amount'] as int,
       fiatCode: json['fiat_code'] as String,
-      minAmount: json['min_amount'] != null ? json['min_amount'] as int : null,
-      maxAmount: json['max_amount'] != null ? json['max_amount'] as int : null,
+      minAmount: json['min_amount'] as int?,
+      maxAmount: json['max_amount'] as int?,
       fiatAmount: json['fiat_amount'] as int,
       paymentMethod: json['payment_method'] as String,
       premium: json['premium'] as int,
-      buyerTradePubkey: json['buyer_trade_pubkey'] != null ? json['buyer_trade_pubkey'] as String : null,
-      sellerTradePubkey: json['seller_trade_pubkey'] != null ? json['seller_trade_pubkey'] as String : null,
-      createdAt: json['created_at'] != null ? json['created_at'] as int : null,
-      expiresAt: json['expires_at'] != null ? json['expires_at'] as int : null,
+      buyerTradePubkey: json['buyer_trade_pubkey'] as String?,
+      sellerTradePubkey: json['seller_trade_pubkey'] as String?,
+      createdAt: json['created_at'] as int?,
+      expiresAt: json['expires_at'] as int?,
     );
   }
lib/features/key_manager/key_management_screen.dart (3)

175-188: Consider adjusting button width ratios.

The 7:3 flex ratio between Import and Refresh buttons may make the Refresh button too narrow on smaller screens, especially since it only contains an icon. Consider testing on various screen sizes or adjusting to 8:2 or making both buttons equal width with the refresh icon and text.


781-786: Consider adding mounted check after dialog dismissal.

After dismissing the dialog, you immediately access ref.read() to trigger the restore process. While the timing is tight, it's a best practice to check mounted after async gaps to prevent accessing disposed widgets.

Apply this diff:

               onPressed: () async {
                 Navigator.of(dialogContext).pop();
-
-                final restoreService = ref.read(restoreServiceProvider);
-                await restoreService.initRestoreProcess();
+                
+                if (mounted) {
+                  final restoreService = ref.read(restoreServiceProvider);
+                  await restoreService.initRestoreProcess();
+                }
               },

609-625: Consider adding accessibility support to icon-only button.

The Refresh button uses only an icon without text. For better accessibility, consider adding a tooltip or semantic label so screen readers can announce the button's purpose.

Apply this diff:

   Widget _buildRefreshUserButton(BuildContext context) {
-    return OutlinedButton(
+    return Tooltip(
+      message: S.of(context)!.refreshUser,
+      child: OutlinedButton(
-      onPressed: () => _showRefreshUserDialog(context),
-      style: OutlinedButton.styleFrom(
-        side: const BorderSide(color: AppTheme.activeColor),
-        shape: RoundedRectangleBorder(
-          borderRadius: BorderRadius.circular(8),
+        onPressed: () => _showRefreshUserDialog(context),
+        style: OutlinedButton.styleFrom(
+          side: const BorderSide(color: AppTheme.activeColor),
+          shape: RoundedRectangleBorder(
+            borderRadius: BorderRadius.circular(8),
+          ),
+          padding: const EdgeInsets.symmetric(vertical: 16),
         ),
-        padding: const EdgeInsets.symmetric(vertical: 16),
+        child: const Icon(
+          LucideIcons.refreshCw,
+          size: 20,
+          color: AppTheme.activeColor,
+        ),
       ),
-      child: const Icon(
-        LucideIcons.refreshCw,
-        size: 20,
-        color: AppTheme.activeColor,
-      ),
     );
   }
lib/features/restore/restore_manager.dart (1)

499-502: Consider extracting magic number to constant.

The 8-second delay is hardcoded and depends on relay timing characteristics. Consider extracting this to a named constant at the class level for better maintainability and potential future configuration.

Apply this diff:

 class RestoreService {
 
   final Ref ref;
   final Logger _logger = Logger();
+  static const Duration _historicalMessageWaitDuration = Duration(seconds: 8);
   StreamSubscription<NostrEvent>? _tempSubscription;
   ...
   
   // Later in the restore method:
-      _logger.i('Restore: waiting 8 seconds for historical messages to be saved...');
+      _logger.i('Restore: waiting ${_historicalMessageWaitDuration.inSeconds} seconds for historical messages to be saved...');
       //WARNING: It is very important to wait here to ensure all historical messages arrive before rebuilding state
       // Relays could send them with delay
-      await Future.delayed(const Duration(seconds: 8));
+      await Future.delayed(_historicalMessageWaitDuration);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 7247917 and b619b2b.

📒 Files selected for processing (26)
  • lib/core/app.dart (2 hunks)
  • lib/data/models/enums/action.dart (1 hunks)
  • lib/data/models/last_trade_index_response.dart (1 hunks)
  • lib/data/models/mostro_message.dart (3 hunks)
  • lib/data/models/orders_request.dart (1 hunks)
  • lib/data/models/orders_response.dart (1 hunks)
  • lib/data/models/payload.dart (1 hunks)
  • lib/data/models/restore_response.dart (1 hunks)
  • lib/data/repositories/open_orders_repository.dart (1 hunks)
  • lib/features/key_manager/import_mnemonic_dialog.dart (1 hunks)
  • lib/features/key_manager/key_management_screen.dart (5 hunks)
  • lib/features/notifications/utils/notification_message_mapper.dart (2 hunks)
  • lib/features/notifications/widgets/notification_item.dart (1 hunks)
  • lib/features/order/notfiers/abstract_mostro_notifier.dart (3 hunks)
  • lib/features/order/notfiers/order_notifier.dart (1 hunks)
  • lib/features/restore/restore_manager.dart (1 hunks)
  • lib/features/restore/restore_overlay.dart (1 hunks)
  • lib/features/restore/restore_progress_notifier.dart (1 hunks)
  • lib/features/restore/restore_progress_state.dart (1 hunks)
  • lib/features/settings/settings_screen.dart (2 hunks)
  • lib/l10n/intl_en.arb (3 hunks)
  • lib/l10n/intl_es.arb (3 hunks)
  • lib/l10n/intl_it.arb (3 hunks)
  • lib/services/mostro_service.dart (3 hunks)
  • lib/shared/utils/mnemonic_validator.dart (1 hunks)
  • test/mocks.mocks.dart (2 hunks)
🧰 Additional context used
📓 Path-based instructions (13)
lib/data/**

📄 CodeRabbit inference engine (AGENTS.md)

Store persistence and API code under lib/data/

Files:

  • lib/data/repositories/open_orders_repository.dart
  • lib/data/models/last_trade_index_response.dart
  • lib/data/models/orders_request.dart
  • lib/data/models/payload.dart
  • lib/data/models/orders_response.dart
  • lib/data/models/restore_response.dart
  • lib/data/models/mostro_message.dart
  • lib/data/models/enums/action.dart
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Use Dart formatter defaults (two-space indentation, trailing commas) and run flutter format before committing
Resolve all Flutter analyzer warnings (flutter analyze must be clean)

**/*.dart: Remove unused imports and unused dependencies
Do not add // ignore: must_be_immutable to classes within generated files; rely on regeneration and existing file-level ignores

Files:

  • lib/data/repositories/open_orders_repository.dart
  • lib/data/models/last_trade_index_response.dart
  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/data/models/orders_request.dart
  • lib/features/settings/settings_screen.dart
  • lib/data/models/payload.dart
  • lib/services/mostro_service.dart
  • lib/shared/utils/mnemonic_validator.dart
  • lib/features/order/notfiers/order_notifier.dart
  • lib/data/models/orders_response.dart
  • lib/data/models/restore_response.dart
  • lib/features/restore/restore_progress_state.dart
  • lib/data/models/mostro_message.dart
  • test/mocks.mocks.dart
  • lib/features/key_manager/import_mnemonic_dialog.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/core/app.dart
  • lib/features/restore/restore_overlay.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
  • lib/data/models/enums/action.dart
  • lib/features/key_manager/key_management_screen.dart
  • lib/features/restore/restore_manager.dart
lib/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Name Riverpod providers as Provider or Notifier

lib/**/*.dart: Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text
Use clear, concise English for variable names, function names, and code comments; all comments must be in English
Target zero flutter analyze issues
Use latest Flutter/Dart APIs (e.g., Color.withValues() instead of withOpacity())
After async operations, check mounted before using BuildContext
Use const constructors where possible

Files:

  • lib/data/repositories/open_orders_repository.dart
  • lib/data/models/last_trade_index_response.dart
  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/data/models/orders_request.dart
  • lib/features/settings/settings_screen.dart
  • lib/data/models/payload.dart
  • lib/services/mostro_service.dart
  • lib/shared/utils/mnemonic_validator.dart
  • lib/features/order/notfiers/order_notifier.dart
  • lib/data/models/orders_response.dart
  • lib/data/models/restore_response.dart
  • lib/features/restore/restore_progress_state.dart
  • lib/data/models/mostro_message.dart
  • lib/features/key_manager/import_mnemonic_dialog.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/core/app.dart
  • lib/features/restore/restore_overlay.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
  • lib/data/models/enums/action.dart
  • lib/features/key_manager/key_management_screen.dart
  • lib/features/restore/restore_manager.dart
lib/data/repositories/**/*.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Use the Repository pattern for all data access (repositories under data/repositories)

Files:

  • lib/data/repositories/open_orders_repository.dart
lib/features/**

📄 CodeRabbit inference engine (AGENTS.md)

Place application feature code under lib/features//, grouped by domain

Files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/features/settings/settings_screen.dart
  • lib/features/order/notfiers/order_notifier.dart
  • lib/features/restore/restore_progress_state.dart
  • lib/features/key_manager/import_mnemonic_dialog.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/restore/restore_overlay.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
  • lib/features/key_manager/key_management_screen.dart
  • lib/features/restore/restore_manager.dart
lib/services/**

📄 CodeRabbit inference engine (AGENTS.md)

Place service-layer code in lib/services/

Files:

  • lib/services/mostro_service.dart
lib/shared/**

📄 CodeRabbit inference engine (AGENTS.md)

Put shared utilities in lib/shared/

Files:

  • lib/shared/utils/mnemonic_validator.dart
test/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.dart: Mirror feature layout for tests under test/
Prefer Mockito fakes generated via build_runner in tests

test/**/*.dart: Unit tests belong in test/; integration tests in integration_test/
Mocks are generated via Mockito; regenerate with dart run build_runner build -d after mock changes

Files:

  • test/mocks.mocks.dart
test/mocks.mocks.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Do not manually edit test/mocks.mocks.dart (Mockito-generated)

Files:

  • test/mocks.mocks.dart
**/*.mocks.dart

📄 CodeRabbit inference engine (CLAUDE.md)

Do not manually edit any *.mocks.dart generated Mockito files

Files:

  • test/mocks.mocks.dart
**/*.{g.dart,mocks.dart}

📄 CodeRabbit inference engine (CLAUDE.md)

Never add per-item ignore comments to generated files; rely on file-level ignores or regenerate

Files:

  • test/mocks.mocks.dart
lib/core/**

📄 CodeRabbit inference engine (AGENTS.md)

Keep dependency wiring in lib/core/

Files:

  • lib/core/app.dart
lib/l10n/*.arb

📄 CodeRabbit inference engine (CLAUDE.md)

lib/l10n/*.arb: Maintain ARB files for en/es/it in lib/l10n/ (intl_en.arb, intl_es.arb, intl_it.arb)
When adding a new localization key, update all three ARB files (en, es, it)
Use proper ARB metadata for parameterized strings
After modifying ARB files, run dart run build_runner build -d to regenerate localization

Files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_it.arb
🧠 Learnings (39)
📓 Common learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
Learnt from: grunch
Repo: MostroP2P/mobile PR: 306
File: docs/architecture/REQUEST_ID_ANALYSIS.md:176-183
Timestamp: 2025-09-17T20:45:32.468Z
Learning: For PR #306 in MostroP2P/mobile repository: This is a documentation-only PR intended to explain how the current requestId system works, not to fix any bugs or issues in the code. The documentation should accurately reflect existing behavior.
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/data/repositories/**/*.dart : Use the Repository pattern for all data access (repositories under data/repositories)

Applied to files:

  • lib/data/repositories/open_orders_repository.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/subscriptions/subscription_manager.dart : SubscriptionManager manages subscriptions, including relay list stream; ensure proper initialization and cleanup

Applied to files:

  • lib/data/repositories/open_orders_repository.dart
  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/services/mostro_service.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/data/models.dart : Export models through lib/data/models.dart

Applied to files:

  • lib/data/models/last_trade_index_response.dart
  • lib/data/models/orders_request.dart
  • lib/features/settings/settings_screen.dart
  • lib/data/models/restore_response.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/relays/relays_notifier.dart : Implement relay operations: syncWithMostroInstance, removeRelayWithBlacklist, addRelayWithSmartValidation, _handleMostroRelayListUpdate

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/features/settings/settings_screen.dart
  • lib/features/order/notfiers/order_notifier.dart
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/services/mostro_service.dart
  • lib/features/order/notfiers/order_notifier.dart
  • test/mocks.mocks.dart
  • lib/core/app.dart
  • lib/features/restore/restore_overlay.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-06-26T15:03:23.529Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/services/mostro_service.dart
  • lib/features/order/notfiers/order_notifier.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/core/mostro_fsm.dart : MostroFSM manages order state transitions (core/mostro_fsm.dart)

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/features/settings/settings_screen.dart
  • lib/features/order/notfiers/order_notifier.dart
  • lib/features/restore/restore_progress_state.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/notifiers/**/*.dart : Encapsulate business logic in Notifiers (use Notifier pattern for complex state logic)

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/features/order/notfiers/order_notifier.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
📚 Learning: 2025-07-20T23:33:17.689Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.689Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/services/mostro_service.dart
📚 Learning: 2025-05-08T16:29:52.154Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/background/background.dart:74-77
Timestamp: 2025-05-08T16:29:52.154Z
Learning: In the Mostro Mobile background service architecture, events aren't stored by the background process. Instead, the background service only checks if events exist in the eventStore and sends notifications for new ones, while the foreground process is responsible for storing and processing events. This is an intentional design decision to separate concerns.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
  • lib/features/settings/settings_screen.dart
  • lib/services/mostro_service.dart
  • lib/core/app.dart
📚 Learning: 2025-05-06T15:49:55.079Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/services/mostro_service.dart:97-103
Timestamp: 2025-05-06T15:49:55.079Z
Learning: In the Mostro protocol, an order cannot be canceled unless it has a valid orderId, so null checks on orderId during cancel operations are unnecessary.

Applied to files:

  • lib/features/order/notfiers/abstract_mostro_notifier.dart
📚 Learning: 2025-08-21T14:45:43.974Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 272
File: lib/features/relays/widgets/relay_selector.dart:13-15
Timestamp: 2025-08-21T14:45:43.974Z
Learning: In the Mostro mobile app's RelaySelector widget (lib/features/relays/widgets/relay_selector.dart), watching relaysProvider.notifier correctly triggers rebuilds because the relaysProvider itself depends on settingsProvider (line 8 in relays_provider.dart). When blacklist changes via toggleMostroRelayBlacklist(), the settingsProvider updates, causing relaysProvider to rebuild, which then notifies widgets watching the notifier. The UI correctly reflects active/inactive states in real-time through this dependency chain.

Applied to files:

  • lib/features/settings/settings_screen.dart
  • lib/core/app.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/settings/settings.dart : Settings model must include blacklistedRelays and maintain backward-compatible serialization

Applied to files:

  • lib/features/settings/settings_screen.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/shared/providers/mostro_database_provider.dart : Initialize Sembast database in shared/providers/mostro_database_provider.dart

Applied to files:

  • lib/features/settings/settings_screen.dart
  • lib/core/app.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/relays/relay.dart : Relay model must track source (user, mostro, defaultConfig) and expose canDelete/canBlacklist semantics

Applied to files:

  • lib/features/settings/settings_screen.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • lib/services/mostro_service.dart
  • test/mocks.mocks.dart
  • lib/data/models/enums/action.dart
📚 Learning: 2025-05-08T16:31:29.582Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/core/models/relay_list_event.dart : Parse NIP-65 kind 10002 events, validate WS URLs, and handle timestamps/null-safety

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-07-08T05:40:47.527Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 127
File: lib/data/models/cant_do.dart:10-27
Timestamp: 2025-07-08T05:40:47.527Z
Learning: In the CantDo model parsing in lib/data/models/cant_do.dart, the inconsistent key naming between 'cant_do' (top-level) and 'cant-do' (nested) is required by the protocol specification and should not be changed as it would break message parsing compatibility.

Applied to files:

  • lib/data/models/mostro_message.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to test/mocks.mocks.dart : Do not manually edit test/mocks.mocks.dart (Mockito-generated)

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to test/**/*.dart : Mocks are generated via Mockito; regenerate with dart run build_runner build -d after mock changes

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to **/*.mocks.dart : Do not manually edit any *.mocks.dart generated Mockito files

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: 2025-10-07T17:31:12.117Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T17:31:12.117Z
Learning: Applies to test/**/*.dart : Prefer Mockito fakes generated via build_runner in tests

Applied to files:

  • test/mocks.mocks.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/generated/l10n.dart : Generated localization entrypoint file is lib/generated/l10n.dart

Applied to files:

  • lib/features/key_manager/import_mnemonic_dialog.dart
📚 Learning: 2025-10-14T21:12:06.887Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:141-154
Timestamp: 2025-10-14T21:12:06.887Z
Learning: In the MostroP2P mobile codebase, the notification system uses a two-layer localization pattern: providers/notifiers (without BuildContext access) call `showCustomMessage()` with string keys (e.g., 'orderTimeoutMaker', 'orderCanceled'), and the UI layer's `NotificationListenerWidget` has a switch statement that maps these keys to localized strings using `S.of(context)`. This architectural pattern properly separates concerns while maintaining full localization support for all user-facing messages.

Applied to files:

  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/core/app.dart
  • lib/features/restore/restore_overlay.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/restore/restore_progress_notifier.dart
  • lib/features/key_manager/key_management_screen.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/notifications/notification_service.dart : Notification service configuration and custom icons should be defined in notification_service.dart

Applied to files:

  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/key_manager/key_management_screen.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/*.dart : Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text

Applied to files:

  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/key_manager/key_management_screen.dart
📚 Learning: 2025-05-06T16:08:19.352Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/shared/providers/app_init_provider.dart:78-95
Timestamp: 2025-05-06T16:08:19.352Z
Learning: In the Mostro Mobile codebase, MostroMessage objects have an 'action' member that can be directly accessed (e.g., mostroMessage.action).

Applied to files:

  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/notifications/widgets/notification_item.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/core/app_routes.dart : Use GoRouter for navigation configured in core/app_routes.dart

Applied to files:

  • lib/core/app.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.

Applied to files:

  • lib/core/app.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/main.dart : Configure timeago locales and app initialization in main.dart

Applied to files:

  • lib/core/app.dart
📚 Learning: 2025-10-07T17:31:12.117Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T17:31:12.117Z
Learning: Applies to lib/**/*.dart : Name Riverpod providers as <Feature>Provider or <Feature>Notifier

Applied to files:

  • lib/core/app.dart
  • lib/features/restore/restore_progress_notifier.dart
📚 Learning: 2025-09-22T19:42:55.332Z
Learnt from: grunch
Repo: MostroP2P/mobile PR: 311
File: lib/services/mostro_service.dart:171-182
Timestamp: 2025-09-22T19:42:55.332Z
Learning: NextTrade payload is supported by both fiatSent and release actions in the Mostro protocol. For fiatSent action, it's specifically used when the maker is the buyer on a range order, as documented in docs/protocol/fiatsent.md with the payload format: { "next_trade": ["<trade pubkey>", <trade index>] }

Applied to files:

  • lib/features/notifications/widgets/notification_item.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/l10n/*.arb : Maintain ARB files for en/es/it in lib/l10n/ (intl_en.arb, intl_es.arb, intl_it.arb)

Applied to files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_it.arb
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/l10n/*.arb : When adding a new localization key, update all three ARB files (en, es, it)

Applied to files:

  • lib/l10n/intl_es.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_it.arb
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/screens/**/*.dart : Pass BuildContext to methods that need localization (S.of(context)!.keyName usage)

Applied to files:

  • lib/features/key_manager/key_management_screen.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/l10n/*.arb : Use proper ARB metadata for parameterized strings

Applied to files:

  • lib/l10n/intl_en.arb
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (23)
lib/data/repositories/open_orders_repository.dart (1)

141-146: LGTM! Clean cache-clearing implementation.

The method correctly clears the in-memory cache and resubscribes to reload orders from relays. The logging is appropriate for debugging restore operations.

lib/shared/utils/mnemonic_validator.dart (1)

7-22: LGTM! Solid mnemonic validation utility.

The implementation properly delegates to the bip39 library with appropriate defensive checks for empty input and exception handling.

lib/data/models/enums/action.dart (1)

41-44: LGTM! Enum expansion is correctly implemented.

The new Action values for the restore feature integrate cleanly with the existing fromString/toString logic via the _valueMap.

lib/core/app.dart (1)

167-174: LGTM! Clean overlay integration.

The Stack-based approach correctly overlays the RestoreOverlay on top of all routed content, ensuring the restore progress UI is always visible when active. The const constructor for RestoreOverlay is efficient.

lib/data/models/payload.dart (1)

40-49: Verify whether restore/lastTradeIndex responses can have empty payloads in JSON.

The original concern is technically valid: if incoming responses for the restore or lastTradeIndex actions contain "payload": {} (empty object), the code will throw UnsupportedError because EmptyPayload is not handled in the Payload.fromJson factory (lines 15-37 of lib/data/models/payload.dart).

However, verification is inconclusive: EmptyPayload() is only used for outgoing messages, and MostroMessage.fromJson skips deserialization if payload is null. Whether incoming responses actually have empty payloads depends on the Mostro protocol specification, which couldn't be confirmed from the codebase alone.

Action required: Check the Mostro protocol specification to confirm whether restore and lastTradeIndex response messages can have empty payloads. If they can, add EmptyPayload support to Payload.fromJson by checking for json.isEmpty and returning EmptyPayload().

lib/features/notifications/widgets/notification_item.dart (1)

124-126: LGTM! New action cases properly handled.

The three new action cases (restore, orders, lastTradeIndex) are appropriately added with break statements, aligning with the restore feature introduced in this PR. The no-op behavior is consistent with other cases in this switch that don't require navigation.

lib/features/order/notfiers/order_notifier.dart (1)

142-154: LGTM! Restore helper methods properly implemented.

The new updateStateFromMessage and updateDispute methods are well-designed for use during restore flows:

  • Both check mounted before updating state (appropriate for StateNotifier per project learnings)
  • Simple, focused implementations that delegate to existing state update logic
  • Public visibility enables external orchestration by RestoreService
lib/features/notifications/utils/notification_message_mapper.dart (2)

87-90: Clarify notification requirements for new actions.

The TODO placeholder strings ('TODO: implement title key if needed') would be displayed to users if notifications are created for restore, orders, or lastTradeIndex actions.

Clarify the notification strategy:

  1. If these actions don't create user-facing notifications: Consider throwing an exception or returning a sentinel value instead of a TODO string to catch misuse during development.
  2. If these actions do create notifications: Complete the localization by adding proper keys to the .arb files before release.

183-186: Same concern: clarify notification requirements for message keys.

Same issue as the title keys above - TODO placeholders would be visible to users. Ensure these actions either don't create notifications, or complete the localization before release.

lib/services/mostro_service.dart (1)

121-124: LGTM! Proper filtering of restore payloads.

The skip logic correctly prevents restore-specific historical events from being processed as normal order events, avoiding interference during subscription setup per the PR objectives.

lib/data/models/mostro_message.dart (2)

40-40: LGTM! Proper EmptyPayload serialization.

Serializing EmptyPayload as null aligns with the protocol specification and properly handles the no-data payload variant introduced in this PR.


47-47: LGTM! Flexible deserialization for restore messages.

Accepting 'order', 'restore', or 'cant-do' keys provides backward compatibility while supporting the new restore protocol, with appropriate priority ordering.

lib/data/models/last_trade_index_response.dart (1)

1-21: LGTM! Clean payload model implementation.

The LastTradeIndexResponse model follows the standard payload pattern:

  • Implements Payload interface correctly
  • Provides proper JSON serialization/deserialization
  • Uses const constructor for efficiency
  • Type identifier matches the action name convention ('last-trade-index')
test/mocks.mocks.dart (2)

849-856: Generated mock looks correct.

The clearCache() mock for MockOpenOrdersRepository is properly generated and corresponds to the new method added to the repository. No manual edits needed.


2930-2947: Generated mocks look correct.

The updateStateFromMessage() and updateDispute() mocks for MockOrderNotifier are properly generated and correspond to the new methods in OrderNotifier. Standard noSuchMethod implementations are appropriate for these void return methods.

lib/features/settings/settings_screen.dart (1)

464-477: Errors are not silently ignored—they are logged and surfaced via RestoreOverlay. The review comment's concerns are unfounded.

The verification confirms that the restore error handling works as intended:

  1. Errors are logged: initRestoreProcess() catches all exceptions at line 705 and logs them via _logger.e() with full stack trace.

  2. Errors are surfaced to UI: At line 707, caught errors update the restoreProgressProvider via showError(), which sets step: RestoreStep.error. The RestoreOverlay watches this provider and renders the error state.

  3. RestoreOverlay is integrated: It's part of the main widget tree (lib/core/app.dart:171), so error states are displayed to users.

  4. The try-catch in settings_screen.dart is defensive: Since initRestoreProcess() internally handles all exceptions and never re-throws, this catch block is redundant but harmless. The misleading comment should ideally be clarified or removed.

The code structure is correct. No changes needed.

lib/features/restore/restore_overlay.dart (1)

8-172: LGTM!

The RestoreOverlay implementation is well-structured with:

  • Proper use of latest Flutter APIs (withValues for color transparency)
  • Good separation of concerns with helper methods
  • Responsive design considerations
  • Correct localization usage via S.of(context)
  • Clean state management via Riverpod
lib/features/key_manager/import_mnemonic_dialog.dart (1)

6-227: LGTM!

The ImportMnemonicDialog implementation is well-designed:

  • Proper validation using external utility
  • Correct mounted check before navigation (Line 46)
  • Good error handling and user feedback
  • Clean UI structure with info bullets
  • Proper resource disposal in dispose()
lib/features/restore/restore_progress_notifier.dart (1)

6-123: LGTM!

The RestoreProgressNotifier implementation follows best practices:

  • Proper mounted checks before state updates in async callbacks (Lines 63, 80, 95)
  • Correct timer cleanup in dispose() (Lines 114-117)
  • Good timeout handling with configurable duration
  • Clean state transitions
lib/features/restore/restore_manager.dart (2)

368-400: TODO acknowledged - dispute creator determination.

The TODO on Line 398 is documented in the PR objectives as a known limitation. The current implementation uses trade index comparison with pubkey verification, which is a reasonable best-effort approach. Future protocol changes may enable more definitive detection.


454-456: Good coordination with restore mode flag.

The static flag AbstractMostroNotifier.setRestoring() creates intentional coordination between restore service and message processing. The implementation correctly:

  • Enables the flag before state reconstruction
  • Disables it after completion
  • Ensures cleanup in error cases via the catch block (Lines 608-612)

This pattern prevents race conditions during restoration as documented in the PR objectives.

Also applies to: 604-606, 608-612

lib/l10n/intl_en.arb (1)

462-914: Localization keys properly maintained across all ARB files.

Verification confirms that new localization keys for import/restore features are present in all three ARB files (intl_en.arb, intl_es.arb, intl_it.arb). Tested keys across all categories returned consistent results across all languages. Ensure dart run build_runner build -d has been run to regenerate localizations after ARB modifications.

lib/features/key_manager/key_management_screen.dart (1)

809-822: Add mounted check after async dialog.

After showDialog completes, the widget may have been disposed. You should check mounted before accessing ref.read() and performing further operations.

Apply this diff:

   Future<void> _showImportMnemonicDialog(BuildContext context) async {
 
     final mnemonic = await showDialog<String>(
       context: context,
       builder: (BuildContext dialogContext) {
         return const ImportMnemonicDialog();
       },
     );
 
-    if (mnemonic != null && mnemonic.isNotEmpty) {
+    if (mounted && mnemonic != null && mnemonic.isNotEmpty) {
       final restoreService = ref.read(restoreServiceProvider);
       await restoreService.importMnemonicAndRestore(mnemonic);
     }
   }
⛔ Skipped due to learnings
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/*.dart : After async operations, check mounted before using BuildContext
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (3)
lib/services/mostro_service.dart (2)

46-96: Defensive coding improvements address previous concerns.

The defensive type checking and null-safety improvements (lines 51-53, 56-58, 78, 85) successfully address the concerns raised in the previous review. The method now safely validates all nested structures before accessing or casting them, and returns false early on any unexpected type.

Consider adding debug logging when a restore payload is detected to aid troubleshooting:

     // RestoreData: has 'restore_data' wrapper with 'orders' and 'disputes' arrays
     if (payload.containsKey('restore_data')) {
+      _logger.d('Detected RestoreData payload, skipping');
       return true;
     }

139-142: Add logging when skipping restore payloads for debugging consistency.

For consistency with the dispute message skip logic (line 135-136) and to aid debugging, consider logging when restore payloads are skipped:

   // Skip restore-specific payloads that arrive as historical events due to temporary subscription
   if (result[0] is Map && _isRestorePayload(result[0] as Map<String, dynamic>)) {
+    _logger.i('Skipping restore-specific payload (handled by RestoreManager)');
     return;
   }
lib/features/restore/restore_manager.dart (1)

368-400: TODO: Incomplete dispute initiation detection.

Line 398 contains a TODO indicating that the current method of determining dispute initiators may need improvement if the protocol changes. The current logic relies on comparing trade indexes, which may not be robust for future protocol versions.

Would you like me to open an issue to track improving this dispute detection logic when the Mostro protocol provides better restoration data?

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b619b2b and bd2b140.

📒 Files selected for processing (5)
  • lib/data/models/restore_response.dart (1 hunks)
  • lib/features/order/notfiers/abstract_mostro_notifier.dart (4 hunks)
  • lib/features/restore/restore_manager.dart (1 hunks)
  • lib/features/restore/restore_mode_provider.dart (1 hunks)
  • lib/services/mostro_service.dart (3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • lib/data/models/restore_response.dart
  • lib/features/order/notfiers/abstract_mostro_notifier.dart
🧰 Additional context used
📓 Path-based instructions (4)
lib/features/**

📄 CodeRabbit inference engine (AGENTS.md)

Place application feature code under lib/features//, grouped by domain

Files:

  • lib/features/restore/restore_mode_provider.dart
  • lib/features/restore/restore_manager.dart
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Use Dart formatter defaults (two-space indentation, trailing commas) and run flutter format before committing
Resolve all Flutter analyzer warnings (flutter analyze must be clean)

**/*.dart: Remove unused imports and unused dependencies
Do not add // ignore: must_be_immutable to classes within generated files; rely on regeneration and existing file-level ignores

Files:

  • lib/features/restore/restore_mode_provider.dart
  • lib/features/restore/restore_manager.dart
  • lib/services/mostro_service.dart
lib/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Name Riverpod providers as Provider or Notifier

lib/**/*.dart: Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text
Use clear, concise English for variable names, function names, and code comments; all comments must be in English
Target zero flutter analyze issues
Use latest Flutter/Dart APIs (e.g., Color.withValues() instead of withOpacity())
After async operations, check mounted before using BuildContext
Use const constructors where possible

Files:

  • lib/features/restore/restore_mode_provider.dart
  • lib/features/restore/restore_manager.dart
  • lib/services/mostro_service.dart
lib/services/**

📄 CodeRabbit inference engine (AGENTS.md)

Place service-layer code in lib/services/

Files:

  • lib/services/mostro_service.dart
🧠 Learnings (12)
📓 Common learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
Learnt from: grunch
Repo: MostroP2P/mobile PR: 306
File: docs/architecture/REQUEST_ID_ANALYSIS.md:176-183
Timestamp: 2025-09-17T20:45:32.468Z
Learning: For PR #306 in MostroP2P/mobile repository: This is a documentation-only PR intended to explain how the current requestId system works, not to fix any bugs or issues in the code. The documentation should accurately reflect existing behavior.
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/*/providers/**/*.dart : Organize Riverpod providers by feature under features/{feature}/providers/

Applied to files:

  • lib/features/restore/restore_mode_provider.dart
📚 Learning: 2025-10-07T17:31:12.117Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-10-07T17:31:12.117Z
Learning: Applies to lib/**/*.dart : Name Riverpod providers as <Feature>Provider or <Feature>Notifier

Applied to files:

  • lib/features/restore/restore_mode_provider.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, Riverpod code generation is used with `Riverpod` annotations. Providers like `eventStorageProvider` are generated in `.g.dart` files from annotated functions in the main provider files. These providers are accessible by importing the main provider file (e.g., `mostro_service_provider.dart`), not by importing a separate provider file.

Applied to files:

  • lib/features/restore/restore_mode_provider.dart
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/restore/restore_mode_provider.dart
  • lib/features/restore/restore_manager.dart
  • lib/services/mostro_service.dart
📚 Learning: 2025-06-26T15:03:23.529Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 127
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:45-54
Timestamp: 2025-06-26T15:03:23.529Z
Learning: In AbstractMostroNotifier, state updates occur for all messages regardless of timestamp to hydrate the OrderNotifier from MostroStorage during sync, while handleEvent is only called for recent messages (within 60 seconds) to prevent re-triggering side effects like notifications and navigation for previously handled messages. This design prevents displaying stale notifications when the app is reopened or brought to the foreground.

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/features/subscriptions/subscription_manager.dart : SubscriptionManager manages subscriptions, including relay list stream; ensure proper initialization and cleanup

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-05-08T16:31:29.582Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/notifications/notification_service.dart:54-59
Timestamp: 2025-05-08T16:31:29.582Z
Learning: In the Nostr protocol, event.id will never be null in events returned by relay subscriptions, so null safety checks for this property are unnecessary.

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/core/models/relay_list_event.dart : Parse NIP-65 kind 10002 events, validate WS URLs, and handle timestamps/null-safety

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-05-06T15:49:26.443Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 74
File: lib/services/mostro_service.dart:70-76
Timestamp: 2025-05-06T15:49:26.443Z
Learning: In the Mostro Mobile codebase, `eventStorageProvider` is exported from `package:mostro_mobile/shared/providers/mostro_service_provider.dart` and not from a separate `event_storage_provider.dart` file.

Applied to files:

  • lib/services/mostro_service.dart
📚 Learning: 2025-07-20T23:33:17.689Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 215
File: lib/features/order/notfiers/order_notifier.dart:0-0
Timestamp: 2025-07-20T23:33:17.689Z
Learning: In AbstractMostroNotifier, the handleEvent method is synchronous and returns void, not Future<void>. Do not suggest adding await to super.handleEvent() calls as this would cause compilation errors.

Applied to files:

  • lib/services/mostro_service.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (7)
lib/services/mostro_service.dart (1)

127-131: LGTM: Good defensive validation.

The validation correctly prevents index access on empty or invalid payloads and provides helpful logging.

lib/features/restore/restore_mode_provider.dart (1)

1-9: LGTM! Clean Riverpod state management.

The provider is well-documented and correctly implements restore mode state using Riverpod's StateProvider. The transition from a static mutable flag to proper state management is a good architectural improvement.

lib/features/restore/restore_manager.dart (5)

57-74: Good provider invalidation pattern.

The invalidation and re-initialization of the keyManagerProvider ensures clean state after mnemonic import. The sequencing of operations is correct.


604-610: Excellent cleanup pattern for restore mode flag.

The restore mode flag is properly disabled in both the success path (line 605) and error path (line 610), ensuring state consistency even when errors occur.


708-722: Robust cleanup in finally block.

The finally block ensures critical cleanup operations (subscription cancellation, key clearing) always execute, and the conditional check prevents calling completeRestore() when already in error state. This is excellent defensive programming.


726-728: Provider follows naming conventions.

The provider is correctly named and structured according to the Riverpod conventions for this codebase.

Based on learnings


499-502: Consider making the message wait time configurable.

The hardcoded 8-second delay assumes all historical messages will arrive within this timeframe. Network conditions and relay response times can vary significantly, potentially causing:

  • Race conditions if messages arrive after 8 seconds
  • Unnecessary waiting if all messages arrive quickly

Consider making this configurable or implementing a more robust synchronization mechanism:

// In class fields:
static const Duration _messageWaitDuration = Duration(seconds: 8);

// Or make it configurable via settings:
final waitDuration = ref.read(settingsProvider).restoreWaitDuration ?? const Duration(seconds: 8);
await Future.delayed(waitDuration);

Alternatively, consider implementing a completion detection mechanism that monitors message arrival rather than relying solely on a fixed delay.

⛔ Skipped due to learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/**/*.dart : After async operations, check mounted before using BuildContext

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (3)
lib/features/restore/restore_manager.dart (3)

185-186: Past review comment not addressed: Add bounds check before array access.

Lines 185-186 access contentList[0] without verifying the list is non-empty. This was flagged in a previous review but has not been fixed. If Mostro returns an empty array, this will throw a RangeError.

Apply this diff to add bounds checking:

     final contentList = jsonDecode(rumor.content!) as List<dynamic>;
+    if (contentList.isEmpty) {
+      _logger.w('Restore: empty content list received');
+      return (ordersMap: <String, int>{}, disputes: <RestoredDispute>[]);
+    }
     final messageData = contentList[0] as Map<String, dynamic>;

274-279: Past review comment not addressed: Add bounds check and null-safe map access.

Multiple safety issues flagged in previous review remain unaddressed:

  1. Lines 274-275: Access contentList[0] without checking if the list is non-empty
  2. Lines 278-279: Access map keys 'order' and 'payload' without null checks

Apply this diff:

     final contentList = jsonDecode(rumor.content!) as List<dynamic>;
+    if (contentList.isEmpty) {
+      throw Exception('Empty content list in orders details response');
+    }
     final messageData = contentList[0] as Map<String, dynamic>;

     // Extract payload from order wrapper
-    final orderWrapper = messageData['order'] as Map<String, dynamic>;
-    final payload = orderWrapper['payload'] as Map<String, dynamic>;
+    final orderWrapper = messageData['order'] as Map<String, dynamic>?;
+    if (orderWrapper == null) {
+      throw Exception('No order wrapper found in response');
+    }
+    final payload = orderWrapper['payload'] as Map<String, dynamic>?;
+    if (payload == null) {
+      throw Exception('No payload found in order wrapper');
+    }

332-333: Past review comment not addressed: Add bounds check for array access.

Lines 332-333 access contentList[0] without verifying the list is non-empty. This was flagged in a previous review but remains unaddressed.

Apply this diff:

     final contentList = jsonDecode(rumor.content!) as List<dynamic>;
+    if (contentList.isEmpty) {
+      _logger.w('Restore: empty content list for last trade index, defaulting to 0');
+      return LastTradeIndexResponse(tradeIndex: 0);
+    }
     final messageData = contentList[0] as Map<String, dynamic>;
🧹 Nitpick comments (2)
lib/features/restore/restore_manager.dart (2)

398-398: Consider addressing the TODO for improved dispute detection.

The TODO comment indicates that the current dispute initiation detection method may need improvement if the protocol changes. While the current double-verification approach is sound, consider documenting the protocol dependency more explicitly or creating a follow-up issue to track potential protocol changes.

Would you like me to open an issue to track this protocol-dependent logic for future improvement?


514-518: Consider making the delay configurable.

The hard-coded 8-second delay (line 518) is necessary to wait for historical messages to arrive, as noted in the comment. However, consider making this duration configurable (e.g., via a constant or settings parameter) to allow easier tuning if relay latency characteristics change.

For example, define a constant at the class level:

static const Duration _historicalMessagesDelay = Duration(seconds: 8);

Then use it:

await Future.delayed(_historicalMessagesDelay);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between bd2b140 and e254926.

📒 Files selected for processing (1)
  • lib/features/restore/restore_manager.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
lib/features/**

📄 CodeRabbit inference engine (AGENTS.md)

Place application feature code under lib/features//, grouped by domain

Files:

  • lib/features/restore/restore_manager.dart
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Use Dart formatter defaults (two-space indentation, trailing commas) and run flutter format before committing
Resolve all Flutter analyzer warnings (flutter analyze must be clean)

**/*.dart: Remove unused imports and unused dependencies
Do not add // ignore: must_be_immutable to classes within generated files; rely on regeneration and existing file-level ignores

Files:

  • lib/features/restore/restore_manager.dart
lib/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Name Riverpod providers as Provider or Notifier

lib/**/*.dart: Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text
Use clear, concise English for variable names, function names, and code comments; all comments must be in English
Target zero flutter analyze issues
Use latest Flutter/Dart APIs (e.g., Color.withValues() instead of withOpacity())
After async operations, check mounted before using BuildContext
Use const constructors where possible

Files:

  • lib/features/restore/restore_manager.dart
🧠 Learnings (3)
📓 Common learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
Learnt from: grunch
Repo: MostroP2P/mobile PR: 306
File: docs/architecture/REQUEST_ID_ANALYSIS.md:176-183
Timestamp: 2025-09-17T20:45:32.468Z
Learning: For PR #306 in MostroP2P/mobile repository: This is a documentation-only PR intended to explain how the current requestId system works, not to fix any bugs or issues in the code. The documentation should accurately reflect existing behavior.
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • lib/features/restore/restore_manager.dart
🔇 Additional comments (1)
lib/features/restore/restore_manager.dart (1)

57-74: LGTM! Good use of provider invalidation.

The pattern of invalidating and re-reading the keyManagerProvider after importing the mnemonic ensures that all dependent providers get fresh instances with the new key. This is the correct approach for refreshing provider state.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
lib/features/restore/restore_manager.dart (1)

515-518: Extract hardcoded delay to a named constant.

The 8-second delay is a magic number that should be extracted to a named constant for better maintainability and self-documentation. This would make it easier to adjust the timing if needed and clarify the purpose of the delay.

Apply this diff to extract the constant:

+  // Delay duration to wait for historical messages from relays during restore
+  static const Duration _historicalMessagesDelay = Duration(seconds: 8);
+
   Future<void> restore(Map<String, int> ordersIds, int lastTradeIndex, OrdersResponse ordersResponse, List<RestoredDispute> disputes) async {
     try {
       ...
       // Wait for historical messages to arrive and be saved to storage
       _logger.i('Restore: waiting 8 seconds for historical messages to be saved...');
       //WARNING: It is very important to wait here to ensure all historical messages arrive before rebuilding state
       // Relays could send them with delay
-      await Future.delayed(const Duration(seconds: 8));
+      await Future.delayed(_historicalMessagesDelay);
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e254926 and 3c59a29.

📒 Files selected for processing (1)
  • lib/features/restore/restore_manager.dart (1 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
lib/features/**

📄 CodeRabbit inference engine (AGENTS.md)

Place application feature code under lib/features//, grouped by domain

Files:

  • lib/features/restore/restore_manager.dart
**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

**/*.dart: Use Dart formatter defaults (two-space indentation, trailing commas) and run flutter format before committing
Resolve all Flutter analyzer warnings (flutter analyze must be clean)

**/*.dart: Remove unused imports and unused dependencies
Do not add // ignore: must_be_immutable to classes within generated files; rely on regeneration and existing file-level ignores

Files:

  • lib/features/restore/restore_manager.dart
lib/**/*.dart

📄 CodeRabbit inference engine (AGENTS.md)

Name Riverpod providers as Provider or Notifier

lib/**/*.dart: Always use localized strings via S.of(context)!.keyName; avoid hardcoded user-facing text
Use clear, concise English for variable names, function names, and code comments; all comments must be in English
Target zero flutter analyze issues
Use latest Flutter/Dart APIs (e.g., Color.withValues() instead of withOpacity())
After async operations, check mounted before using BuildContext
Use const constructors where possible

Files:

  • lib/features/restore/restore_manager.dart
🧠 Learnings (4)
📓 Common learnings
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.
Learnt from: grunch
Repo: MostroP2P/mobile PR: 306
File: docs/architecture/REQUEST_ID_ANALYSIS.md:176-183
Timestamp: 2025-09-17T20:45:32.468Z
Learning: For PR #306 in MostroP2P/mobile repository: This is a documentation-only PR intended to explain how the current requestId system works, not to fix any bugs or issues in the code. The documentation should accurately reflect existing behavior.
📚 Learning: 2025-10-21T21:47:03.451Z
Learnt from: Catrya
Repo: MostroP2P/mobile PR: 327
File: lib/features/order/notfiers/abstract_mostro_notifier.dart:157-182
Timestamp: 2025-10-21T21:47:03.451Z
Learning: In MostroP2P/mobile, for Action.canceled handling in abstract_mostro_notifier.dart (Riverpod StateNotifier), do not add mounted checks after async sessionNotifier.deleteSession(orderId) as they break order state synchronization during app restart. The Action.canceled flow contains critical business logic that must complete fully; Riverpod handles provider disposal automatically. Mounted checks should only protect UI operations, not business logic in StateNotifiers.

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-06-04T19:35:20.209Z
Learnt from: chebizarro
Repo: MostroP2P/mobile PR: 110
File: test/notifiers/take_order_notifier_test.dart:72-74
Timestamp: 2025-06-04T19:35:20.209Z
Learning: MostroService methods like takeBuyOrder() and takeSellOrder() return Future<void> and trigger side effects through other mechanisms rather than direct return values. When testing these methods, focus on verifying method calls and testing state changes through the provider system rather than mocking return values.

Applied to files:

  • lib/features/restore/restore_manager.dart
📚 Learning: 2025-10-22T12:29:26.971Z
Learnt from: CR
Repo: MostroP2P/mobile PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-10-22T12:29:26.971Z
Learning: Applies to lib/core/mostro_fsm.dart : MostroFSM manages order state transitions (core/mostro_fsm.dart)

Applied to files:

  • lib/features/restore/restore_manager.dart
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build
🔇 Additional comments (2)
lib/features/restore/restore_manager.dart (2)

633-740: Well-structured multi-stage restore workflow.

The orchestration logic correctly implements the 4-stage restore process described in the PR objectives:

  1. Stage 1: Getting restore data (orders map and disputes)
  2. Stage 2: Getting order details
  3. Stage 3: Getting last trade index
  4. Stage 4: Processing and restoring sessions

The error handling, cleanup in the finally block, and temporary subscription management are all properly implemented. The special handling for empty orders (lines 681-689) ensures the key index is still updated even when no orders exist.


368-400: Good security verification for dispute initiation detection.

The method implements proper security checks by:

  1. Verifying the session's trade pubkey matches the order's buyer/seller pubkey for the given role
  2. Comparing trade indexes to determine who initiated the dispute
  3. Defaulting to peer-initiated (false) if verification fails

This defensive approach prevents incorrect dispute attribution due to session mismatches.

@BraCR10
Copy link
Contributor Author

BraCR10 commented Nov 11, 2025

Ready for Review

Notes

  1. There’s currently no clear way to determine who created a dispute — that’s why the TODO comment was added.
    image

  2. Mostrod must be running with this commit or any later version.

@grunch grunch requested a review from Catrya November 13, 2025 13:21
Copy link
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Me ha funcionado bastante bien, pero hubo una vez que me salió error en la app al intentar importar el usuario, estos fueron los logs de mostrod:

2025-11-19T00:16:40.990977Z  INFO mostrod::app::restore_session: Starting background restore session for master key: 858cb808efb31edc6b8c63259d8655515ab47b4a0fd340e79140cde5dd150aca
2025-11-19T00:16:40.993441Z  INFO mostrod::db: Background restore session completed with 2 orders, 0 disputes
2025-11-19T00:16:40.993519Z  INFO mostrod::app::restore_session: Restore session response sent to user 620ea3eebbd2d7bfca0fbe37b6e1b5a55dbe8075aa5fb9cbb0bde371ee456419
2025-11-19T00:16:41.155040Z  INFO mostrod::util: sender key 82fa8cb978b43c79b2156585bac2c011176a21d2aead6d9f7c575c005be88390 - receiver key 620ea3eebbd2d7bfca0fbe37b6e1b5a55dbe8075aa5fb9cbb0bde371ee456419
2025-11-19T00:16:41.155872Z  INFO mostrod::util: Sending DM, Event ID: df50fd5f2030cbc2e9ca681efbf6e70207e6ffe3618731af1aa5b467ad60dce0 to 620ea3eebbd2d7bfca0fbe37b6e1b5a55dbe8075aa5fb9cbb0bde371ee456419 with payload: "{\"restore\":{\"version\":1,\"request_id\":null,\"trade_index\":null,\"action\":\"restore-session\",\"payload\":{\"restore_data\":{\"orders\":[{\"order_id\":\"16a40294-919f-4d57-92e5-80cfd2376290\",\"trade_index\":2,\"status\":\"pending\"},{\"order_id\":\"d4950e52-cc57-41b9-bb69-fc58228f05d9\",\"trade_index\":1,\"status\":\"active\"}],\"disputes\":[]}}}}"
2025-11-19T00:16:41.613018Z  WARN mostrod::app: Error unwrapping gift: malformed signature at line 1 column 1422

Pero al volver a intentarlo me funcionó bien, ese mensaje de error pasa a veces en mostrod pero igual lo aviso aqui por si caso

Copy link
Member

@Catrya Catrya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Intenté restaurar un usuario antiguo que tengo con mostro-cli, mostrod envía que hay 8 órdenes en total y aunque la app lo recibe, solo muestra 2 órdenes en la UI.

Este es el mensaje que envia mostrod:

2025-11-19T00:51:22.892070Z  INFO mostrod::db: Background restore session completed with 8 orders, 0 disputes
2025-11-19T00:51:22.892199Z  INFO mostrod::app::restore_session: Restore session response sent to user 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf
2025-11-19T00:51:23.075859Z  INFO mostrod::util: sender key 82fa8cb978b43c79b2156585bac2c011176a21d2aead6d9f7c575c005be88390 - receiver key 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf
2025-11-19T00:51:23.076892Z  INFO mostrod::util: Sending DM, Event ID: 591055211d95706748533330d3f61db97af3a8cc86034c95329e80e6aeb160b4 to 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf with payload: "{\"restore\":{\"version\":1,\"request_id\":null,\"trade_index\":null,\"action\":\"restore-session\",\"payload\":{\"restore_data\":{\"orders\":[{\"order_id\":\"d4950e52-cc57-41b9-bb69-fc58228f05d9\",\"trade_index\":51,\"status\":\"active\"},{\"order_id\":\"1400e742-7db4-4363-b315-03b6b6918111\",\"trade_index\":33,\"status\":\"active\"},{\"order_id\":\"8221930d-bf6b-40bb-b2da-a8f4e9315dfb\",\"trade_index\":34,\"status\":\"active\"},{\"order_id\":\"e186ee33-a264-4503-a25c-06e4397a82cf\",\"trade_index\":37,\"status\":\"active\"},{\"order_id\":\"f6ea4b1d-f92c-49b9-a777-d3b472a6e036\",\"trade_index\":38,\"status\":\"active\"},{\"order_id\":\"abfa3fb4-01fb-469a-b763-9f8e3ff7de1e\",\"trade_index\":40,\"status\":\"active\"},{\"order_id\":\"2dfd3da6-a189-445e-9fdc-a11c7c6a1f24\",\"trade_index\":43,\"status\":\"fiat-sent\"},{\"order_id\":\"45c02db6-5d21-4c43-919c-eb194c76ca0f\",\"trade_index\":48,\"status\":\"pending\"}],\"disputes\":[]}}}}"
2025-11-19T00:51:23.434725Z  INFO mostrod::util: sender key 82fa8cb978b43c79b2156585bac2c011176a21d2aead6d9f7c575c005be88390 - receiver key 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf
2025-11-19T00:51:23.436443Z  INFO mostrod::util: Sending DM, Event ID: 59406aae5651422cccf7bc63eddeae80870b309d2de58f305fb73720820b179b to 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf with payload: "{\"order\":{\"version\":1,\"request_id\":1763513483241,\"trade_index\":null,\"action\":\"orders\",\"payload\":{\"orders\":[{\"id\":\"d4950e52-cc57-41b9-bb69-fc58228f05d9\",\"kind\":\"sell\",\"status\":\"active\",\"amount\":903,\"fiat_code\":\"ARS\",\"min_amount\":null,\"max_amount\":null,\"fiat_amount\":1234,\"payment_method\":\"MODO\",\"premium\":0,\"buyer_trade_pubkey\":\"9b708fc76cdfa7556166bdfe1949f51890dc83036d98ba6ec23b5382d40ffa1b\",\"seller_trade_pubkey\":\"620ea3eebbd2d7bfca0fbe37b6e1b5a55dbe8075aa5fb9cbb0bde371ee456419\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"1400e742-7db4-4363-b315-03b6b6918111\",\"kind\":\"buy\",\"status\":\"active\",\"amount\":656,\"fiat_code\":\"CUP\",\"min_amount\":300,\"max_amount\":1000,\"fiat_amount\":300,\"payment_method\":\"Transfermovil\",\"premium\":0,\"buyer_trade_pubkey\":\"f0518eb155b46e633fa5ad52f2636a266c49958b150597dc8032943d0501b9e8\",\"seller_trade_pubkey\":\"a36641acae07b0f9f2f25a3369492f16fdbb9e3294e028ef300e89775a30dd46\",\"buyer_invoice\":\"lnbc6540n1p53yq72pp5ca39ncfqwe7ea5vmthpg8cc5f78vye88vrt6qr3tqdc9vw9gu8kqdqqcqzzsxqyz5vqsp5nj0ha0k3mhz5c95taecwtd7uwhswmmryyjvxyulffmj3kqp7d64s9qxpqysgq7p6qe9qcankt8x035kh3g3t3s2p5jautxjyz3elk29vf7tzzedrkc4dr384urfc7exzjynelr0eag93gvgsjsx5422m3nmr4l3jxmfgpqtnphx\",\"created_at\":null,\"expires_at\":null},{\"id\":\"8221930d-bf6b-40bb-b2da-a8f4e9315dfb\",\"kind\":\"buy\",\"status\":\"active\",\"amount\":895,\"fiat_code\":\"MLC\",\"min_amount\":2,\"max_amount\":10,\"fiat_amount\":2,\"payment_method\":\"Transferencia Bancaria,Efectivo\",\"premium\":0,\"buyer_trade_pubkey\":\"d138f22eaef17793cf4e544b4206c8b7916c8fac93a936d88e6921c42458d1b1\",\"seller_trade_pubkey\":\"d8b2dbaa02889fa7f0d81d5fdd684182a063eec6e83f32c63dd517bd539cc4fc\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"e186ee33-a264-4503-a25c-06e4397a82cf\",\"kind\":\"buy\",\"status\":\"active\",\"amount\":644,\"fiat_code\":\"CUP\",\"min_amount\":300,\"max_amount\":1000,\"fiat_amount\":300,\"payment_method\":\"EnZona\",\"premium\":0,\"buyer_trade_pubkey\":\"4ef51a823e6b6b79244abe28d7b777fc912aba7e52b65fdb9dfd4ce64d051b7a\",\"seller_trade_pubkey\":\"a640eaa86053198a0d6079da122aaa4327b4efe6d7370faf6ebef3a0e11a976e\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"f6ea4b1d-f92c-49b9-a777-d3b472a6e036\",\"kind\":\"buy\",\"status\":\"active\",\"amount\":881,\"fiat_code\":\"MLC\",\"min_amount\":null,\"max_amount\":null,\"fiat_amount\":2,\"payment_method\":\"Transferencia Bancaria\",\"premium\":0,\"buyer_trade_pubkey\":\"32b89ba2bc14d9a93ae39cf51ca5a24a9cb3eb9eaba672fee6bc19d318eca034\",\"seller_trade_pubkey\":\"cd0bba88405fadb96aa481b34f9acdffbfe9a6ec09f620f833d883a077d59dad\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"abfa3fb4-01fb-469a-b763-9f8e3ff7de1e\",\"kind\":\"buy\",\"status\":\"active\",\"amount\":856,\"fiat_code\":\"CUP\",\"min_amount\":null,\"max_amount\":null,\"fiat_amount\":400,\"payment_method\":\"EnZona\",\"premium\":0,\"buyer_trade_pubkey\":\"0aaa43d21584548f8929cf01f0b93e4e15b22c158a7af14661390cc036ccbf64\",\"seller_trade_pubkey\":\"8c20092c30445ca76f1c1a7b0e6e796d04436517b641baccc1763229bbcf4e5f\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"2dfd3da6-a189-445e-9fdc-a11c7c6a1f24\",\"kind\":\"buy\",\"status\":\"fiat-sent\",\"amount\":645,\"fiat_code\":\"CUP\",\"min_amount\":null,\"max_amount\":null,\"fiat_amount\":300,\"payment_method\":\"Transfermovil\",\"premium\":0,\"buyer_trade_pubkey\":\"ad593988f36a07dc004ac3e12fad465acf8d34b649b65babe0c49b9a9a3f1ff0\",\"seller_trade_pubkey\":\"b016c0fdedd78975a8fa39f397fe4fdd8a89b6cbfd51a107ec39c3fcfdeb4616\",\"buyer_invoice\":\"spiralboot92@walletofsatoshi.com\",\"created_at\":null,\"expires_at\":null},{\"id\":\"45c02db6-5d21-4c43-919c-eb194c76ca0f\",\"kind\":\"sell\",\"status\":\"pending\",\"amount\":0,\"fiat_code\":\"CUP\",\"min_amount\":null,\"max_amount\":null,\"fiat_amount\":500,\"payment_method\":\"test\",\"premium\":0,\"seller_trade_pubkey\":\"de66228dbb847eb3f04a720e6e63573c42c6767cee0e40b48740ff69c38f3f2e\",\"created_at\":null,\"expires_at\":null}]}}}"
2025-11-19T00:51:23.785434Z  INFO mostrod::app::last_trade_index: User with pubkey: d1ebe4b36e251d5f30da171e6df700b616030775929eb0bc1e32b830ac82640e requested last trade index
2025-11-19T00:51:23.785710Z  INFO mostrod::app::last_trade_index: Last trade index: 51
2025-11-19T00:51:23.785804Z  INFO mostrod::util: sender key 82fa8cb978b43c79b2156585bac2c011176a21d2aead6d9f7c575c005be88390 - receiver key 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf
2025-11-19T00:51:23.786363Z  INFO mostrod::util: Sending DM, Event ID: 4494a94cb215108b21ecea5440956e6246aeaf18a2dfa158cdcef0c17efde444 to 519c20f0dc60797d3a8b344123d035bd2f8e80d838fd9729a6cc2774d3de97bf with payload: "{\"restore\":{\"version\":1,\"request_id\":null,\"trade_index\":51,\"action\":\"last-trade-index\",\"payload\":null}}"

pero la app solo muestra 2 ordenes

Image

estos son los logs de la app en 2 momentos diferentes cuando intenté resataurar ese usuario
1er intento:
logs.txt
en este me llama la atención esto, que no salió la 2da vez que lo intenté:

[ERROR:flutter/runtime/dart_vm_initializer.cc(40)] Unhandled Exception: Invalid argument(s): Trade key does not match derived key
#0      SessionStorage._decodeSession (package:mostro_mobile/data/repositories/session_storage.dart:40:7)
#1      SessionStorage.fromDbMap (package:mostro_mobile/data/repositories/session_storage.dart:25:12)
#2      BaseStorage.find.<anonymous closure> (package:mostro_mobile/data/repositories/base_storage.dart:75:23)
#3      MappedListIterable.elementAt (dart:_internal/iterable.dart:442:31)
#4      ListIterator.moveNext (dart:_internal/iterable.dart:371:26)
#5      new _List._ofEfficientLengthIterable (dart:core-patch/array.dart:170:27)
#6      new _List.of (dart:core-patch/array.dart:134:20)
#7      new List.of (dart:core-patch/array_patch.dart:39:50)
#8      ListIterable.toList (dart:_internal/iterable.dart:224:7)
#9      BaseStorage.find (package:mostro_mobile/data/repositories/base_storage.dart:76:10)
<asynchronous suspension>
#10     SessionNotifier._cleanup (package:mostro_mobile/shared/notifiers/session_notifier.dart:73:29)
<asynchronous suspension>

2do intento:
logs1.txt

Estas son las 8 ordenes, las que muestra la UI son la de trade index 51 y 48

  1. Order ID: d4950e52-cc57-41b9-bb69-fc58228f05d9
     Trade Index: 51
     Status: "active"

  2. Order ID: 1400e742-7db4-4363-b315-03b6b6918111
     Trade Index: 33
     Status: "active"

  3. Order ID: 8221930d-bf6b-40bb-b2da-a8f4e9315dfb
     Trade Index: 34
     Status: "active"

  4. Order ID: e186ee33-a264-4503-a25c-06e4397a82cf
     Trade Index: 37
     Status: "active"

  5. Order ID: f6ea4b1d-f92c-49b9-a777-d3b472a6e036
     Trade Index: 38
     Status: "active"

  6. Order ID: abfa3fb4-01fb-469a-b763-9f8e3ff7de1e
     Trade Index: 40
     Status: "active"

  7. Order ID: 2dfd3da6-a189-445e-9fdc-a11c7c6a1f24
     Trade Index: 43
     Status: "fiat-sent"

  8. Order ID: 45c02db6-5d21-4c43-919c-eb194c76ca0f
     Trade Index: 48
     Status: "pending"

@grunch
Copy link
Member

grunch commented Nov 19, 2025

Intenté restaurar un usuario antiguo que tengo con mostro-cli, mostrod envía que hay 8 órdenes en total y aunque la app lo recibe, solo muestra 2 órdenes en la UI.

Excelente review, voy a fusionar el PR, cuando puedas @Catrya crea un issue en ingles con esta info así lo tenemos pendiente

Copy link
Member

@grunch grunch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tACK

@grunch grunch merged commit 6c2d641 into MostroP2P:main Nov 19, 2025
2 checks passed
@grunch
Copy link
Member

grunch commented Nov 19, 2025

@BraCR10 great job!!! congratulations on your first Mostro contribution 🥳

Please add a lightning invoice with amount of 400k sats as a comment of this PR

@BraCR10
Copy link
Contributor Author

BraCR10 commented Nov 19, 2025

Thks sir! @grunch

lnbc4m1p53mhhspp5dcax0w2zrdk7l7uq6dexscx3y75pz08xx4ev47a72c26825hpztqdqqcqzpuxqyz5vqsp57wlu50480vyceq4m89cjqpmwe39z6uv5kjynuct34xclfp366k4s9qxpqysgqgw9n083edr59sxph7ry8884x908smcrt3j9a3kuwkwy309skeq8xpl2yvjerale87qdepw200z4kqa72ny42duymagxcael36xcsq6cpkq96g4

@grunch
Copy link
Member

grunch commented Nov 19, 2025

lnbc4m1p53mhhspp5dcax0w2zrdk7l7uq6dexscx3y75pz08xx4ev47a72c26825hpztqdqqcqzpuxqyz5vqsp57wlu50480vyceq4m89cjqpmwe39z6uv5kjynuct34xclfp366k4s9qxpqysgqgw9n083edr59sxph7ry8884x908smcrt3j9a3kuwkwy309skeq8xpl2yvjerale87qdepw200z4kqa72ny42duymagxcael36xcsq6cpkq96g4

Payment hash: 6e3a67b9421b6deffb80d3726860d127a8113ce63572cafbbe5615a3aa970896
Payment status: SUCCEEDED, preimage: 6b80c7d06e32bd134879908e835565a9d95bec7d6d4bf99c46437776abd674aa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants