Implementation of Key management#34
Conversation
WalkthroughThis pull request introduces significant architectural changes to the Mostro Mobile application, focusing on key management, session handling, and initialization processes. The modifications enhance the application's security and initialization flow by introducing new classes like Changes
Sequence DiagramsequenceDiagram
participant App
participant AppInitializer
participant KeyManager
participant SessionManager
participant MostroRepository
App->>AppInitializer: Initialize
AppInitializer->>KeyManager: Check Master Key
alt No Master Key
KeyManager->>KeyManager: Generate Master Key
end
AppInitializer->>SessionManager: Initialize Sessions
AppInitializer->>MostroRepository: Load Messages
AppInitializer-->>App: Initialization Complete
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Actionable comments posted: 7
🧹 Nitpick comments (37)
lib/features/take_order/screens/take_sell_order_screen.dart (1)
122-122: Handle potentialnullvalue gracefully.By switching to
order?.amount,valmay benull. Currently, iforderisnull, the screen prompts the user to enter an invoice for “null sats,” which may be confusing. Consider using a fallback value or preventing invoice submission whenvalisnull.Below is a possible improvement to handle a
nullvalmore gracefully:-final val = order?.amount; +final val = order?.amount ?? 0; ... Text( "Please enter a Lightning Invoice for $val sats:", style: TextStyle(color: AppTheme.cream1, fontSize: 16), ), ... onPressed: () { final invoice = invoiceController.text.trim(); if (invoice.isNotEmpty && val != 0) { orderDetailsNotifier.sendInvoice(orderId, invoice, val); } },lib/services/nostr_service.dart (5)
82-84: Validate the private key input.
Currently, the method directly delegates toNostrUtils.generateKeyPairFromPrivateKey(privateKey). Consider adding input validation or exception handling so that invalid keys produce meaningful error messages rather than unexpected runtime exceptions withinNostrUtils.
100-101: Add logging for decryption attempts.
While the method properly checks_isInitialized, the success or failure of decryption is not logged. Consider adding debug or info logs for improved traceability, especially since decryption failures are a common source of silent errors.
109-110: Add error handling for rumor creation.
The code delegates toNostrUtils.createRumor. Consider wrapping this in try-catch or verifying success to handle potential exceptions or null returns gracefully (if the utility method can fail).Also applies to: 111-113
115-116: Add logging for sealing process.
Similar to rumor creation, the sealing process depends on a utility method. If an exception occurs, it may be challenging to locate the exact source. A small debug statement before or after theNostrUtils.createSealcall would assist in diagnosing issues in production.Also applies to: 117-119
121-122: Clarify usage of createWrap parameters.
The method is straightforward, but consider clarifying how thesealedContentis derived and howrecipientPubKeyis validated—either via inline comments or parameter documentation. This will help other contributors integrate the method correctly.Also applies to: 123-125
lib/data/models/cant_do.dart (2)
3-4: Consider documenting the class.
Providing a short class-level doc comment can help clarify the purpose and usage of this payload.
12-16: Implement thetoJsonmethod or remove the throw.
Currently, the method is unimplemented, which may lead to runtime errors if serialization is attempted.Here’s a possible minimal implementation:
Map<String, dynamic> toJson() { - throw UnimplementedError(); + return { + 'cant_do': cantDo, + }; }lib/data/models/session.dart (1)
12-12: Naming consistency betweenorderIdand the JSON keyevent_id.
Usingevent_idin JSON butorderIdin code may cause confusion. For consistency, consider aligning these names if possible.lib/features/order/notfiers/order_notifier.dart (1)
24-37: Subscription error handling and logging are done well.
Consider a more robust logging mechanism or user feedback if the subscription fails repeatedly. Current design is appropriate for initial release.lib/data/repositories/mostro_repository.dart (1)
74-80:saveMessages()
Iterates over_messages, writing each item. Be mindful of potential concurrency or performance with large message sets.lib/data/repositories/session_manager.dart (2)
13-17: Expiration policy and constants
DefiningsessionExpirationHours,cleanupIntervalMinutes, andmaxBatchSizeis straightforward. Evaluate if 48 hours is adequate in your usage context.
88-96:_decodeSession
Injecting the derived keys into the session map before callingSession.fromJsonis clever. Confirm that using the same master key for each decode is expected.lib/services/mostro_service.dart (2)
54-61: Consistent message creation for invoices
UsingnewMessagewithAction.addInvoicekeeps the logic consistent. The array payload[null, invoice, null]might benefit from a comment explaining these placeholders.
108-119: Unifying message creation
newMessageprovides a single place to define the NIP-59orderstructure. Consider adding a brief comment describing each field’s eventual use (e.g.,request_id,trade_index).lib/shared/utils/nostr_utils.dart (2)
147-165: Clarity in naming
The label “Rumor” might be non-obvious to new contributors. Consider adding a doc comment explaining thatcreateRumorencrypts the kind=1 event content.
167-181: Duplicate logic withcreateRumor
createSealshares a similar encryption flow. If the logic remains the same, consider unifying them to reduce repetition.lib/app/app_settings.dart (3)
6-6: Typographical oversight
It’s spelledintial. Recommend renaming toinitialfor clarity.- factory AppSettings.intial() => AppSettings(fullPrivacyMode: false); + factory AppSettings.initial() => AppSettings(fullPrivacyMode: false);
8-9:copyWithmethod
Using a requiredfullPrivacyModeenforces explicit updates. Future expansions might benefit from optional named parameters if more properties are introduced.
11-11: Extra blank line
No functional impact, but consider removing if unintended.lib/shared/providers/mostro_service_provider.dart (1)
5-6: Consider documenting the reason for separate providers.
The introduction ofsession_manager_provider.dartandstorage_providers.dartis beneficial for a more modular design. However, it might be good to include short explanatory comments near these imports to clarify their roles—for instance, whether they provide secure or ephemeral session data.lib/shared/providers/app_init_provider.dart (1)
7-22: Validate the order in which initialization steps occur.
The initialization sequence appears correct: master key check → generate key → session manager init → message loading → notifiers setup. However, be cautious about potential issues if any of these steps fail or take longer than expected (e.g., network calls, large message sets). Consider adding minimal logging or error handling to ensure that partial failures are properly traced and reported.lib/features/key_manager/key_storage.dart (3)
10-12: Handle potential write failures or concurrency.
While writing the master key is straightforward, it's recommended to handle or log any possible failure scenarios (e.g.,write(...)throwing an exception). Also verify that multiple concurrent writes from different screens or threads won't cause conflicts.
18-20: Make sure mnemonic usage is ephemeral if possible.
Use caution in storing mnemonics for prolonged periods. Best practice often emphasizes ephemeral in-memory usage for seed phrases to mitigate compromise risk. A disclaimer or doc note might be beneficial.
26-28: Handle possible index misconfiguration.
Storing an integer index for keys is straightforward, but ensure that the system references the correct index (especially if the user might reset or restore data). A fallback or validation step might help avoid corrupted states.lib/main.dart (1)
18-20: Consider lazy initialization.The
SharedPreferencesAsync()andFlutterSecureStorage()instances are initialized eagerly during app startup. Consider deferring their instantiation until needed (lazy initialization) to improve startup performance, unless you have a specific requirement to initialize them at launch.lib/features/key_manager/key_derivator.dart (3)
6-8: Keep class documentation short and clear.The class doc comments are an excellent start. Consider adding an example usage snippet for
KeyDerivatorso other developers understand typical usage patterns.
17-20: Add negative tests.
isMnemonicValidreturns a boolean, but consider how you handle invalid mnemonics in the broader system. It may be prudent to add negative test cases or explicit logging for invalid results in the calling code.
34-43: Handle neutered node scenarios robustly.You already throw an exception if
child.privateKey == null. It may be beneficial to detect whether the node is neutered at creation time or provide a fallback path. This can prevent partial, unhandled failures if the derivation path is not as expected.lib/data/models/mostro_message.dart (2)
7-9: Document new fields.The addition of
idandtradeIndexis useful, but add doc comments to help future maintainers understand their purpose, especially howtradeIndexis derived or expected to be used.
12-12: Parameter order clarity.The constructor’s parameters have grown. Consider rearranging or documenting them to clarify which fields are optional vs. required, and what each one represents.
lib/app/app.dart (2)
45-49: Loading state UI is straightforward.
Presenting a loading indicator is good. Consider adding a brand-appropriate splash or skeleton screen if there's potential for a prolonged initialization period.
50-54: Error state handling is appropriate.
Displaying the error message is good for debugging. For production, ensure that sensitive or cryptic error messages aren't exposed to the user.test/services/key_derivator_test.dart (2)
46-50: Auto-generated mnemonic is validated.
Ensuring generated mnemonics pass your own validation logic is key. Could add negative tests where an invalid mnemonic is rejected to confirm error handling.
66-67: Future test group is ready for more.
Looks like a placeholder for additional Mostro-specific key derivation tests. Good forward planning.Would you like me to draft any additional tests to accelerate coverage?
lib/data/models/order.dart (1)
59-62: Validate that always-including these fields is acceptable.
Be aware that always serializingcreated_at,expires_at,buyer_token, andseller_token, even if null, can introduce potential confusion or break systems expecting optional fields to be omitted.pubspec.yaml (1)
91-91: Confirm the reintroduction ofmockito.
Reinstatingmockitohelps with test mocks, but ensure that older or replaced mocking libraries are fully deprecated to avoid conflicts.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
pubspec.lockis excluded by!**/*.lock
📒 Files selected for processing (38)
lib/app/app.dart(1 hunks)lib/app/app_routes.dart(0 hunks)lib/app/app_settings.dart(1 hunks)lib/app/config.dart(1 hunks)lib/data/models/cant_do.dart(1 hunks)lib/data/models/enums/storage_keys.dart(1 hunks)lib/data/models/mostro_message.dart(1 hunks)lib/data/models/order.dart(2 hunks)lib/data/models/payload.dart(2 hunks)lib/data/models/session.dart(1 hunks)lib/data/repositories/mostro_repository.dart(3 hunks)lib/data/repositories/secure_storage_manager.dart(0 hunks)lib/data/repositories/session_manager.dart(1 hunks)lib/features/add_order/notifiers/add_order_notifier.dart(2 hunks)lib/features/key_manager/key_derivator.dart(1 hunks)lib/features/key_manager/key_manager.dart(1 hunks)lib/features/key_manager/key_manager_errors.dart(1 hunks)lib/features/key_manager/key_manager_provider.dart(1 hunks)lib/features/key_manager/key_storage.dart(1 hunks)lib/features/order/notfiers/order_notifier.dart(1 hunks)lib/features/order/providers/order_notifier_provider.dart(1 hunks)lib/features/take_order/notifiers/take_buy_order_notifier.dart(1 hunks)lib/features/take_order/notifiers/take_sell_order_notifier.dart(1 hunks)lib/features/take_order/screens/take_sell_order_screen.dart(1 hunks)lib/main.dart(1 hunks)lib/notifiers/mostro_orders_notifier.dart(0 hunks)lib/services/mostro_service.dart(2 hunks)lib/services/nostr_service.dart(3 hunks)lib/shared/notifiers/app_settings_controller.dart(2 hunks)lib/shared/providers/app_init_provider.dart(1 hunks)lib/shared/providers/mostro_service_provider.dart(2 hunks)lib/shared/providers/session_manager_provider.dart(1 hunks)lib/shared/providers/shared_preferences_provider.dart(0 hunks)lib/shared/providers/storage_providers.dart(1 hunks)lib/shared/utils/nostr_utils.dart(1 hunks)pubspec.yaml(2 hunks)test/models/order_test.dart(1 hunks)test/services/key_derivator_test.dart(1 hunks)
💤 Files with no reviewable changes (4)
- lib/notifiers/mostro_orders_notifier.dart
- lib/app/app_routes.dart
- lib/shared/providers/shared_preferences_provider.dart
- lib/data/repositories/secure_storage_manager.dart
✅ Files skipped from review due to trivial changes (1)
- lib/app/config.dart
🔇 Additional comments (101)
lib/services/nostr_service.dart (1)
23-23: Favor consistent callback structure for maintainability.
The inline callback foronRelayListeningis succinct, but consider inline documentation or at least a single comment if additional logic is introduced later (e.g., tracking all active relays, handling partial connections, etc.).lib/data/models/cant_do.dart (1)
6-8: Validate presence and type ofcant_do.
Consider verifying thatjson['cant_do']is valid (e.g., non-null and a string). Throwing a more descriptive error can help with debugging when the field is missing or malformed.lib/data/models/payload.dart (2)
1-1: Import statement check.
The import forcant_do.dartlooks good, but ensure it does not introduce dependency cycles.
14-15: Confirm 'cant_do' key usage.
This logic is correct for handling the newcant_dopayload. Verify that server responses consistently include this key and that it matches the renamedtypeif you decide to rename it.lib/data/models/session.dart (4)
7-10: Consider verifying if keys should be serialized internally or handled only by SessionManager.
Storing complete key pairs directly in this class could lead to unintentional exposures if the object is serialized. Currently,toJson()avoids outputting these keys, which is good; however, explicitly clarifying whether these fields must remain in memory or if they need extra protection would improve clarity.
14-20: Constructor readability is good.
The constructor organizes required parameters effectively. Ensure thatorderIddefaults remain meaningful if not provided.
22-27: Confirm the intent to exclude cryptographic keys fromtoJson().
This approach is appropriate from a security standpoint, but if you intend to reconstruct the session object from JSON alone, the keys won't be restored unless you re-inject them, which you do later viaSessionManager. Validate that this design aligns with app requirements.
32-37: Potential mismatch withtoJson()for master/trade keys.
fromJsonreadsmaster_keyandtrade_key, yet these fields are absent in thetoJson()output. This design offloads key restoration to separate storage, which is acceptable if carefully handled. Otherwise, storing partial data may lead to confusion.lib/features/key_manager/key_manager.dart (7)
12-15: MethodhasMasterKey()is straightforward.
This simple check is clear and efficient. Be sure to handle any potential storage exceptions upstream if needed.
17-26: Validate master key generation coverage and error handling.
While generating a new mnemonic and master key is correct, consider explicit error handling if_derivator.generateMnemonic()or_derivator.extendedKeyFromMnemonic(...)fails unexpectedly.
28-37: Good practice to throwMasterKeyNotFoundException.
Ensuring a consistent exception for missing keys is helpful. Consider clarifying if this condition indicates a first-time user or if it implies potential data corruption.
39-42: Retrieval of mnemonic is correct.
No concerns: returningnullif no mnemonic is found is intuitive.
44-58: Incrementing the trading key index after derivation is appropriate.
Ensure concurrency control if multiple trade keys might be derived in parallel, e.g., by different parts of the code. Also double check that skippingawait _storage.storeTradeKeyIndex(currentIndex + 1);on error won’t cause index misalignment.
60-69:deriveTradeKeyFromIndex(int index)method is efficient.
This approach is straightforward. Potential concurrency or re-entrancy issues with storing or skipping index updates do not apply here, so it’s simpler.
71-73: MethodgetCurrentKeyIndex()is neat.
This is a clean wrapper around_storage.readTradeKeyIndex().lib/features/order/notfiers/order_notifier.dart (4)
9-14: Constructor clarifies initial state retrieval.
Instantiating state fromgetOrderByIdor defaulting toAction.notFoundis sensible. Properly handles the scenario where the order does not exist.
39-41: Error handling with notifications is succinct.
This helps ensure the user is aware of streaming or connectivity issues. Possibly add reconnection logic if needed.
43-80: Switch-case usage for different actions is well-organized.
The separate handling for eachActionis readable. Consider adding comments for unimplementedActioncases or merging them into a catch-all category only if you’re sure they never occur in normal operation.
83-87: Dispose logic is correct.
Canceling the subscription prevents memory leaks and ensures an orderly teardown.lib/data/repositories/mostro_repository.dart (11)
2-3: Import usage recognized.
Reading and writing withjsonplus secure storage is sensible for sensitive data handling.
13-13: Storing theFlutterSecureStorageinstance is fine.
Secure storage is a good choice for sensitive data. Just be careful when reading large volumes of data if performance is critical.
16-16: Changed_subscriptionskey type
Now usingint(aligned withsession.keyIndex), which clarifies the subscription mapping.
18-18: Constructor injection
The repository now depends on bothMostroServiceandFlutterSecureStorage. This is a positive shift for testability and single-responsibility.
20-21: Getter methods for messages
getOrderByIdandallMessagesare straightforward. No immediate concerns.
23-41: Subscription logic persists messages to secure storage
Good approach for real-time updates. Make sure_messagesremains consistent if storage writes fail. Potentially consider concurrency or partial failures.
43-44: Resubscribe byorderId
This is simplistic. As soon asorderIdyields a session, re-establish the stream. Validatesession != nullupstream if the service unexpectedly returns null.
70-70: Asynchronous cancellation
ChangingcancelOrderto aFuture<void>is good for ensuring the call has completed.
82-86:saveMessage(MostroMessage)
Storing single messages is more granular thansaveMessages(). Good approach for incremental updates.
88-91:deleteMessage
Cleanly deletes from in-memory cache and secure storage. This keeps data consistent and prevents orphans.
93-105:loadMessages()
Attempts to deserialize all known message entries. The try/catch is crucial to avoid halting on corrupted entries. Possibly add logging for partial failures.lib/data/repositories/session_manager.dart (11)
8-12: Use of in-memory map_sessions
Reflecting sessions bykeyIndexis logical. Keep in mind concurrency if multiple parts of the code might update sessions simultaneously.
18-20: Constructor auto-runs_initializeCleanup()
This is a useful pattern for housekeeping. Ensure that in test scenarios, you manage or mock out the timer.
22-36: Initialization from storage
Decoding all session entries ininit()is good. Consider chunking or pagination if storage grows large.
38-53:newSession
Retrieves master key, obtains the next index, derives a trade key, and creates aSession. This is well-structured, but ensure concurrency is safe if multiple sessions or key derivations happen at once.
55-60:saveSession
Serializes and writes the session. The secure approach is consistent with the rest of the code.
62-68:getSessionByOrderId
Uses a simple .firstWhere approach. This is concise and left out concurrency complexities.
70-86:loadSession
Loads a session from storage if not cached. The error handling is correct. Might consider logging or removing the failing entry if decode fails.
98-102:deleteSession
Removes session from_sessionsand secure storage. Straightforward.
104-134:clearExpiredSessions
Properly checks for expired sessions, removing them in manageable batches. This ensures that corrupted entries are also removed, which is beneficial for data integrity.
136-143: Cleanup timer
Periodic disposal of expired sessions is a nice strategy. Evaluate if user activity might require a more dynamic or event-based approach.
145-150: Dispose pattern
Cancels the timer to avoid memory leaks. Good practice.lib/services/mostro_service.dart (13)
2-3: Imports for hashing and hex encoding
No issues found. Usage ofcryptoandconvertis consistent and correct for cryptographic hashing and hex operations.
9-9: New import for session manager
Integration with the newSessionManageraligns with the key management refactoring in the PR.
14-14: Addition ofSessionManagerfield
Storing_sessionManageras a final property centralizes session handling withinMostroService.
16-16: Constructor updated to acceptSessionManager
This change injects session capabilities into the service and keeps responsibilities clear.
19-28: Consider adding error handling in the subscription flow
Decryption errors inasyncMapwill propagate as stream errors. This might be acceptable, but ensure the UI or calling code can gracefully handle and display such errors.
32-34: Simple pass-through
Fetching the session by order ID is straightforward. No issues noted.
39-39: Enhanced code structure for order-taking
Creating a new session for each order and leveragingnewMessageclarifies the workflow fortakeSellOrder. It improves readability and maintainability.Also applies to: 48-49
65-68: Symmetry withtakeSellOrder
Implementation parallelstakeSellOrderwith consistent handling fortakeBuyOrder.
73-88: Robust handling of partial or full privacy
This method cleanly adjusts content based on thefullPrivacyflag. Signing logic is correct for the hashed JSON. Consider adding checks ifmessage['order']is null or malformed.
94-95:cancelOrderprocedure
Straightforward usage ofnewMessagewithAction.cancel. No immediate issues.
99-101:sendFiatSentutility
Consistent approach to building and sending the message. No concerns found.
103-106:releaseOrderprocedure
Same pattern of message creation and sending, consistent with other actions.
146-161: Potential mismatch in key usage
createRumoris always passedsession.tradeKeyas the sender key pair, even whenfullPrivacyisfalseandkeySet = session.masterKey. Confirm this aligns with your intended cryptographic design and usage of keys.lib/shared/utils/nostr_utils.dart (1)
198-227: Orchestrated encryption for NIP-59 events
This multi-step flow (rumor, seal, wrap) looks well-structured. Validate thatisValidPrivateKeysupports all key types (e.g., BIP32, ephemeral) to avoid cryptographic edge cases.lib/app/app_settings.dart (2)
2-2: Renamed property for privacy
Switching fromisFirstLaunchtofullPrivacyModebetter reflects the feature’s function.
4-4: Mandatory constructor parameter
Enforcing initialization offullPrivacyModeensures its state is never ambiguous.lib/features/key_manager/key_manager_errors.dart (2)
1-7:MasterKeyNotFoundException
Clear exception for missing master key scenarios. The custom message aids debugging.
9-15:TradeKeyDerivationException
Targeted exception class for derivation failures. Separating it from other errors improves maintainability.lib/shared/providers/storage_providers.dart (2)
5-7:secureStorageProviderintroduction
Providing a singleFlutterSecureStorageinstance across the app ensures consistency and easier testing.
9-11:sharedPreferencesProviderstub
ThrowingUnimplementedErroris an effective placeholder. Just ensure it’s overridden properly inmainso no runtime error occurs.lib/shared/providers/session_manager_provider.dart (2)
1-4: Imports look good.
All necessary imports are present for Riverpod, session management, key management, and storage.
6-10: Provider definition is coherent.
ThesessionManagerProvidercorrectly composes theSessionManagerby injecting required dependencies (keyManager,secureStorage) viaref.read. This approach aligns well with Riverpod best practices.lib/features/order/providers/order_notifier_provider.dart (2)
1-4: Imports are appropriate.
Essential imports for the notifier, models, and repository have been included. Satisfies the requirements for Riverpod-based state management.
6-15: Use ofStateNotifierProvider.familyis correct.
The code properly constructs anOrderNotifierbased on theorderId, ensuring each order is tracked separately. The usage of.watch()to retrieve the repository is clean and aligns with Riverpod.lib/shared/notifiers/app_settings_controller.dart (3)
3-4: Imports updated to use shared providers and typed storage keys.
This is an improvement in maintainability. Explicit references tostorage_keys.dartandstorage_providers.dartreduce the chance of typos and mismatches.
14-16: Default privacy mode set totrue.
By defaulting totrue, users start with full privacy mode if no preference is set. Ensure this matches the desired UX.
18-18: State copy is straightforward.
UpdatingAppSettingswithfullPrivacyModeis consistent with the new setting logic.lib/features/key_manager/key_manager_provider.dart (1)
7-15: Key manager composition is sound.
Dependencies are retrieved fromsecureStorageProviderandsharedPreferencesProvider, encapsulated inKeyStorage, and combined with a specific derivation path inKeyDerivator. The pattern is consistent and modular.lib/shared/providers/mostro_service_provider.dart (1)
16-17: Confirm that thesecureStorageProvidermeets all storage requirements.
While passingsecureStoragetoMostroRepositoryis logical, verify thatMostroRepositoryis fully aware of encryption and data lifecycles. For example, confirm that this storage is suitable for all repository interactions where sensitive data is handled, and that error handling is in place to manage read/write failures.lib/data/models/enums/storage_keys.dart (2)
1-25: Validate string-to-enum conversion logic.
Enums with a_valueMapsignificantly reduce the risk of typos when referencing storage keys. Double-check that each key's string correctly matches the usage throughout the codebase, especially aroundkey_indexvs.full_privacy. Additionally, ensure that the thrownArgumentErroris handled gracefully upstream.
27-53: Ensure consistency across secure storage keys.
The structure mirrors that ofSharedPreferencesKeys, which is great for consistency. Review possible future expansions (e.g., ephemeral keys, refresh tokens) to confirm the naming scheme remains straightforward and predictable. This uniform approach helps maintain clarity and prevents collisions.lib/features/key_manager/key_storage.dart (3)
5-9: Confirm that bothFlutterSecureStorageandSharedPreferencesAsyncalign with security requirements.
Depending on the threat model, verify that storing the trade key index in shared preferences doesn't leak sensitive usage patterns. Consider disclaimers or documentation if partial data exposure is acceptable.
14-16: Balance convenience with security on read operations.
Reading the master key can be sensitive. Confirm that there are guardrails in place if this is called from multiple points, and that your code never logs or exposes the returned value.
30-32: Default index is 1; verify this matches the upstream logic.
Ensure the logic that increments or checks this index correlates with your app’s derivation strategy. If the app expects an initial index of 0 in certain scenarios, this could lead to subtle off-by-one issues.lib/main.dart (2)
3-3: Ensure proper usage of these new imports.The imports for
flutter_secure_storage,storage_providers, andshared_preferencesintroduce secure storage and preference management. Confirm that platform differences (e.g., iOS Keychain vs. Android Keystore) are properly handled and that the new providers are used consistently throughout the codebase.Also applies to: 8-8, 10-10
26-27: Double-check error handling on provider overrides.While overriding these providers works for injecting shared preferences and secure storage, consider adding error trapping in case initialization fails (e.g., device-specific storage issues). This ensures you can handle such incidents gracefully during runtime.
test/models/order_test.dart (1)
38-38: Validate changes in JSON structure.Switching from
contenttopayloadfor accessingorderreflects a new JSON structure. Ensure all usage across the codebase is consistently updated to avoid missing references tocontent. Also confirm that older references tocontentor a hybrid structure won't cause runtime errors or test failures.lib/features/key_manager/key_derivator.dart (5)
1-4: Confirm library compatibility and updates.These imports (
bip39,bip32,convert,dart_nostr) rely on active maintenance and correct versioning. Ensure you're using up-to-date, stable versions of these cryptographic libraries and confirm they don’t conflict with each other or with the rest of the application.
11-12: Non-validated derivation path.While you accept
derivationPathin the constructor, confirm that you handle incorrect or unexpected formats. You might wish to add a format check or at least some default in case the derivation path is invalid.
13-16: Leverage cryptographic randomness best practices.Your
generateMnemonic()function delegates tobip39.generateMnemonic(). Ensure that the underlying random source meets cryptographic-grade randomness. In general,bip39is secure, but be sure it remains updated.
21-27: Validate child index usage.
masterPrivateKeyFromMnemonicderives a child path by appending/0. Ensure this aligns with your specs for identity mode vs. ephemeral trade keys. Some standards usem/44'/...while others might differ. Confirm the correct path for your use case.
44-48: Check for off-by-one risk in key pair derivation.
privateToPublicKeyusesdart_nostrto generate a public key. Confirm you’re deriving the correct index for your ephemeral or identity keys before calling this method to avoid accidental mismatch or reuse.lib/data/models/mostro_message.dart (2)
19-20: Ensure backward compatibility.You’re still writing
'request_id': idin the JSON. If older code expects'request_id', confirm that it also handles the new field name'id'properly or consider renaming the JSON key if consistent with your domain model.
30-35: Verify robust error handling and fallback logic.Your factory method transitions from
'content'to'payload', checks for'cant-do', extracts'tradeIndex', and sets'id'. Ensure all edge cases are covered—especially iforder,payload, orcant-dois missing or incomplete. This also applies to the new fields'trade_index'and'id', which might be absent in older or partial messages.Also applies to: 41-42, 45-51
lib/features/take_order/notifiers/take_buy_order_notifier.dart (1)
39-39: Use caution with null assertion onstate.id!.
While it's likely handled by upstream logic, forcing a null check with!can throw an unhandled exception ifidbecomes unexpectedly null. Consider adding validation or a fallback to ensure safe navigation.lib/app/app.dart (3)
10-10: Good addition ofapp_init_provider.dart.
Importingapp_init_provideris essential for asynchronous initialization. Ensure that it remains a stable dependency to prevent circular imports.
17-17: Initialization state handling is well-structured.
Storing theinitAsyncValuein a local variable clarifies the read operation from the provider. This improves readability compared to chaining method calls.
19-44: Handle final route changes indatastate carefully.
Inside thedatabranch, you listen to the auth state and navigate the user accordingly. Confirm that the app won't re-trigger identical navigations when the AuthState transitions remain unchanged. If re-navigations are problematic, consider gating repeated calls based on the prior state.lib/features/take_order/notifiers/take_sell_order_notifier.dart (1)
36-36: Method signature update to allowint? amountis consistent.
Ensuringamountcan be null aligns with optional user inputs; confirm your repository and upstream calls can handle this scenario gracefully.test/services/key_derivator_test.dart (6)
1-3: Test file organization looks good.
Import statements are minimal and purposeful. Great job keeping test dependencies clean.
4-6: Documentation references are clear and helpful.
Linking to NIP-06 ensures future readers can understand these test vectors.
7-9: Logical test grouping.
Creating a dedicated group for NIP-06 tests clarifies the purpose. Keep grouping consistent for future expansions.
10-26: Test Vector 1 covers essential checks.
The mnemonic validity, private key derivation, and public key checks comprehensively validate the first example. No improvements needed here.
28-44: Test Vector 2 demonstrates consistency.
Another thorough coverage of mnemonic validity, private, and public key derivations. Good job verifying a second vector for robust coverage.
52-63: Child key derivation test is thorough.
Verifying the derived key length alongside the exact expected hex fosters confidence in correctness.lib/features/add_order/notifiers/add_order_notifier.dart (1)
30-31: Consider double-checking ID initialization to avoid null usage.
Currently, the ID is set tonull, presumably awaiting assignment from an external source (e.g., a back-end response). Ensure that subsequent logic accounts for a potentially null ID, or supply a placeholder value if needed to prevent any runtime crashes before theidis set.lib/data/models/order.dart (2)
36-36: Confirm that a defaultpremiumof 0 meets expected business logic.
Previously, the default was 1, so changing it to 0 could affect pricing or calculations downstream. Ensure no features implicitly rely onpremiumbeing 1.
54-55: Always includingmin_amountandmax_amountmight introduce null fields.
If the server or other clients expect these fields to be absent rather than null, it could cause data format issues. Verify that sending them as null is safe.pubspec.yaml (2)
75-75: Check for compatibility ofbip32 ^2.0.0with existing cryptographic flows.
Switching frombip32_bip44tobip32might impact key derivation. Verify that all modules expecting BIP44 functionalities are updated accordingly.
92-92: Make use ofbuild_runnerfor efficient code generation.
Having addedbuild_runnercan streamline code generation tasks (e.g., JSON serializable). Verify your build scripts are updated to leverage this dependency.
| //await AuthUtils.savePrivateKeyAndPin( | ||
| // keyPair.private, ''); // Consider adding a password parameter |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Ensure deliberate handling of private keys.
These lines are commented out but highlight a key area of concern: secure storage and retrieval of private keys. Before re-enabling, ensure that the private keys are protected by secure storage mechanisms (e.g., encrypted keystore) or appropriate password protection.
Would you like help making this more secure or a quick example code snippet demonstrating best practices with secure storage?
| Future<void> sendMessage(String orderId, String receiverPubkey, | ||
| Map<String, dynamic> content) async { | ||
| try { | ||
| final session = _sessionManager.getSessionByOrderId(orderId); | ||
| String finalContent; | ||
| if (!session!.fullPrivacy) { | ||
| content['order']?['trade_index'] = session.keyIndex; | ||
| final sha256Digest = | ||
| sha256.convert(utf8.encode(jsonEncode(content['order']))); | ||
| final hashHex = hex.encode(sha256Digest.bytes); | ||
| final signature = session.tradeKey.sign(hashHex); | ||
| finalContent = jsonEncode([content, signature]); | ||
| } else { | ||
| finalContent = jsonEncode([content, null]); | ||
| } | ||
| final event = | ||
| await createNIP59Event(finalContent, receiverPubkey, session); | ||
| await _nostrService.publishEvent(event); | ||
| } catch (e) { | ||
| // catch and throw and log and stuff | ||
| print(e); | ||
| } | ||
| } |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Null-safety and error handling
Using the forced non-null (session!) could cause runtime failures if the session is missing. A safer approach would be to handle null explicitly. Also, using structured logs might be preferable to print(e).
| static Future<NostrEvent> createWrap(NostrKeyPairs wrapperKeyPair, | ||
| String sealedContent, String recipientPubKey) async { | ||
| final wrapEvent = NostrEvent.fromPartialData( | ||
| kind: 1059, | ||
| content: sealedContent, | ||
| keyPairs: wrapperKeyPair, | ||
| tags: [ | ||
| ["p", recipientPubKey] | ||
| ], | ||
| createdAt: createdAt, | ||
| createdAt: DateTime.now(), |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Wrap event creation
Using DateTime.now() here can reveal local system timing. For maximum privacy, consider adopting the randomNow() approach as in createSeal.
| break; | ||
| case Action.payInvoice: | ||
| navProvider.go('/pay_invoice/${state.requestId!}'); | ||
| navProvider.go('/pay_invoice/${state.id!}'); |
There was a problem hiding this comment.
Prevent potential runtime error if state.id is null.
Similarly to the previous block, calling state.id! without verifying non-null can cause a crash. Validate id before navigation.
| switch (state.action) { | ||
| case Action.newOrder: | ||
| navProvider.go('/order_confirmed/${state.requestId!}'); | ||
| navProvider.go('/order_confirmed/${state.id!}'); |
There was a problem hiding this comment.
🛠️ Refactor suggestion
Guard against null id before navigation.
Using state.id! assumes the field will never be null at this point. If there's any chance the ID could remain uninitialized, the app will crash. Consider guarding against null or providing an alternative path.
- navProvider.go('/order_confirmed/${state.id!}');
+ if (state.id != null) {
+ navProvider.go('/order_confirmed/${state.id}');
+ } else {
+ notifProvider.showInformation('Order ID is missing; cannot proceed.');
+ }Committable suggestion skipped: line range outside the PR's diff.
Fixes type Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Catrya
left a comment
There was a problem hiding this comment.
Error when taking an order that I previously cancelled
When I take a sales order I use trade key X. If I cancel it before entering the invoice, the order is republished in pending status again. If I take it again later, I use trade key Y to send the take-sell action. When I enter the invoice, this appears in the mostrod logs:
2025-01-07T04:02:08.499413Z ERROR mostrod::app::add_invoice: Buyer pubkey not found for order c1fdf86b-99df-4f3c-a6b3-26ca787bf017!
I think it is because the client is sending the message with the add-invoice action with trade key X instead of with trade key Y, which is the correct one. I assume this because the same error occurs in mostro-cli, and when I take that order for the second time, it does not go through the screen of whether to take the order or not, but instead goes directly to the screen of entering the invoice, this one:

There was a problem hiding this comment.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (1)
Line range hint
41-54: Enhance security for sensitive invoice data.Given that this PR implements key management functionality, we should ensure sensitive payment data is handled securely.
Consider implementing:
- Secure text input that prevents screenshots
- Clear invoice data from memory after submission
- Avoid logging invoice details
TextFormField( controller: invoiceController, style: const TextStyle(color: AppTheme.cream1), + obscureText: false, // Consider making this configurable + enableSuggestions: false, + autocorrect: false, decoration: InputDecoration( border: OutlineInputBorder( borderRadius: BorderRadius.circular(8), ), labelText: "Lightning Invoice", labelStyle: const TextStyle(color: AppTheme.grey2), hintText: "Enter invoice here", hintStyle: const TextStyle(color: AppTheme.grey2), filled: true, fillColor: AppTheme.dark1, + // Add visual indicator for secure input + prefixIcon: const Icon(Icons.security), ), ),Also, ensure to clear the invoice data:
@override void dispose() { // Clear sensitive data invoiceController.clear(); super.dispose(); }
🧹 Nitpick comments (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (1)
Line range hint
88-93: Enhance invoice submission with validation and feedback.The current implementation lacks proper validation and user feedback for the invoice submission process.
Consider adding:
- Lightning invoice format validation
- Loading state during submission
- Error handling
- Success feedback
onPressed: () { + if (!mounted) return; final invoice = invoiceController.text.trim(); - if (invoice.isNotEmpty) { - mostroRepo.sendInvoice(orderId, invoice); + if (invoice.isEmpty) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please enter an invoice')), + ); + return; + } + + // Basic BOLT11 invoice format validation + if (!invoice.toLowerCase().startsWith('ln')) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Invalid Lightning invoice format')), + ); + return; + } + + showDialog( + context: context, + barrierDismissible: false, + builder: (context) => const Center(child: CircularProgressIndicator()), + ); + + try { + await mostroRepo.sendInvoice(orderId, invoice); + if (!mounted) return; + Navigator.pop(context); // Dismiss loading + context.go('/success'); // Navigate to success screen + } catch (e) { + if (!mounted) return; + Navigator.pop(context); // Dismiss loading + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Failed to submit invoice: ${e.toString()}')), + ); } },
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
lib/features/key_manager/key_manager_provider.dart(1 hunks)lib/features/take_order/notifiers/take_sell_order_notifier.dart(1 hunks)lib/features/take_order/screens/add_lightning_invoice_screen.dart(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- lib/features/take_order/notifiers/take_sell_order_notifier.dart
- lib/features/key_manager/key_manager_provider.dart
🔇 Additional comments (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (1)
6-6: LGTM! Clean import additions.The new imports are well-organized and properly support the enhanced order management functionality.
Also applies to: 10-10
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Actionable comments posted: 0
🔭 Outside diff range comments (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (1)
Line range hint
104-109: Add validation and error handling to the submit flow.The submit flow could benefit from:
- Lightning invoice format validation
- Error handling similar to the cancel flow
- Loading state during submission
onPressed: () { final invoice = invoiceController.text.trim(); - if (invoice.isNotEmpty) { - mostroRepo.sendInvoice(orderId, invoice); + if (!isValidLightningInvoice(invoice)) { + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Please enter a valid Lightning invoice')), + ); + return; + } + try { + mostroRepo.sendInvoice(orderId, invoice); + context.go('/'); + } catch (e) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Failed to submit invoice: ${e.toString()}')), + ); } },
🧹 Nitpick comments (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (1)
71-81: Enhance error handling and logging.Consider improving the error handling:
- Add logging for unexpected action types in the default case
- Consider tracking cancellation errors in analytics for better monitoring
switch (message.action) { case action.Action.takeBuy: ref.read(takeBuyOrderNotifierProvider(orderId).notifier).dispose(); break; case action.Action.takeSell: ref.read(takeSellOrderNotifierProvider(orderId).notifier).dispose(); break; default: - // Log unexpected action type + debugPrint('Unexpected action type: ${message.action}'); + // Consider adding analytics tracking here break; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
lib/features/take_order/screens/add_lightning_invoice_screen.dart(2 hunks)
🔇 Additional comments (2)
lib/features/take_order/screens/add_lightning_invoice_screen.dart (2)
6-6: LGTM! Import statements are properly organized.The new imports are necessary for the enhanced cancel order flow and follow proper conventions.
Also applies to: 10-10
63-92:⚠️ Potential issueFix critical issues in the cancel order flow.
There are several issues in the current implementation:
mostroRepo.cancelOrder(orderId)is called twice (before and inside try-catch)- The navigation call after try-catch is unreachable
- Navigation occurs even if cancellation fails
Apply this diff to fix the issues:
- mostroRepo.cancelOrder(orderId); try { if (message == null) { context.go('/'); return; } // Dispose notifier first switch (message.action) { case action.Action.takeBuy: ref.read(takeBuyOrderNotifierProvider(orderId).notifier).dispose(); break; case action.Action.takeSell: ref.read(takeSellOrderNotifierProvider(orderId).notifier).dispose(); break; default: // Log unexpected action type break; } // Then cancel order mostroRepo.cancelOrder(orderId); context.go('/'); } catch (e) { // Show error to user ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('Failed to cancel order: ${e.toString()}')), ); - } - context.go('/'); + }Run this script to check for similar patterns in other files:
✅ Verification successful
Confirmed: Double cancellation issue is isolated to this file
The review comment is correct. The double cancellation and navigation issues are unique to
add_lightning_invoice_screen.dart. Other files in the codebase implement the cancel order flow correctly with a single call tocancelOrder.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for potential double cancellation patterns in other files # Look for files that might have similar cancel order implementations rg -l "cancelOrder.*context\.go"Length of output: 34
Script:
#!/bin/bash # Search for cancelOrder calls and their context rg "cancelOrder" -A 5 -B 5 # Search for files containing both mostroRepo and context.go rg -l "mostroRepo.*context\.go|context\.go.*mostroRepo"Length of output: 6261
Catrya
left a comment
There was a problem hiding this comment.
Hi @chebizarro
- This error keeps appearing #34 (review)
When a buyer takes a sales order and cancels it before entering the invoice, the client shows it again in the order list because it is again in Pending status (that's fine) But then when they tries to take it again, it doesn't even go to waiting-buyer-invoice status but the order remains in Pending, however from the client it goes directly to the screen to enter the invoice and when doing so mostrod shows: 2025-01-14T16:09:27.602868Z ERROR mostrod::app::add_invoice: Buyer pubkey not found for order 0450429e-8b4d-4491-b05f-2495bdd1bc5e!
-
I can't test that same error when taking a purchase order, because this screen appears when taking it (order goes to status
waiting-payment)

-
If I try to take a purchase order with range even if I put the amount of sats I want to buy, mostrod sends
Cant-dowithout_of_range_fiat_amountI suppose the client is not sending that amount -
Range orders cannot be created yet
-
When creating orders the
fixedbutton does not work. It also requires that the amount of sats must be completed, otherwise it will not be created, however that amount of sats is not sent to mostrod because it is always published at market price
|
This PR code is moved to |
|
I'm closing this one in favor of wip branch, re-open it if is needed @chebizarro |
* added KeyManager class * Add key manager and related providers * added full privacy mode setting to app settings * Changed SecureStorageManager to SessionManager * Moved session storage/retrieval to SessionManager * Added separate wrap, seal and rumor functions * master key and trade key integration * minor edits * Minor fixes to session expiration * implementation of key manager features * verified sending new orders with full privacy * message and session serialization and retrieval * updated mostro message to handle cant-do * Implementation of order persistence between restarts * change order > content to order > payload * Initialize and load sessions at startup * Change rumor content to array * Debugging signing * Added support for cant-do * add buy/sell order now working * Update lib/data/models/cant_do.dart Fixes type Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * should fix #34 (review) * Update lib/features/take_order/screens/add_lightning_invoice_screen.dart Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * added localization extension for retrieving localized strings based on Action type and AbstractOrderNotifier to consolidate orders * Consolidate all OrderNotifiers as subclasses of AbstractOrderNotifier * minor changes to order notifier and notification notifiers * Filter user orders and updated Add Order screen to match web client * Added OrderBook feature * Added Drawer to Home Screen * Unifed order provider fixed * added Chat and Database support * Rationalised TakeOrderNotifier * removed bloc dependancy * Added integration and mocked unit tests * Integration tests for Create Sell Order * Added Key Management and Relay screens * Added extra key manager methods for importing existing key * Added rating feature * renamed order book and chat to trades and messages respectively * switch persistence to sembat and updated dart_nostr to latest version * updated mostro storage to use sembast * Clear caches * update tests * Added Mostro Instance Screen and updated OrderNotifier strings * Add QR Code Reader to Lightning Invoice screen * Separate our Lightning invoice components to widgets * Consolidated Drawer Screens * Order Screens complete * Updated launch icons * Major revisions * Changes to startup and added web support * Added public test nostr relay and daemon as default * set permissions for secure storage * UX clean up * Add mostro pubkey filter getting events * fixed privacy mode * added default relay * Updated Settings Screen * update build workflow * More buildflow fixes * Updated Take Order Screen and Home Screen Order List * improve Lightning Invoice Screen * Improve images * Add currency flag to my trades widget * Fix alignment on currency flag * Fix take order bug * fix for build action * works in full privacy mode * refactored app settings to be more reactive * More settings refactoring * Modified signing function * start of mostro service refactor * Refactored Mostro Service Updated My Trades Detail Screens Added 'Fiat Sent' and 'Release' buttons to My Trades Detail Screens Refactored Order Providers Added Mobile App Version and Git Hash to About Screen * Fixes error creating new order with ln address #38 Updated release build script Updated dependencies * Addresses When creating a new identity, the orders from the previous identity are not forgotten #36 * Started ChatRoom refactor Updated Action and CantDo enums Updated CantDo and Action string suggestions * Updated i10n strings to latest suggestions Included separate CantDo strings in i10n Added MostroMessageDetail widget to TradeDetailScreen * Implementation of Rate Counterpart * Partial implementation of Increment trade index only on success #35 * Changed AddLightingForm to back to the Home Screen on back/close * Revert Increment trade index only on success #35 fix * Major refactor of MostroService including deprecation of MostroRepository All MostroRepoistory in memory persistence operations are now embedded in MostroStorage which is now a direct dependency of MostroService * Added BaseStorage abstract class Refactored Session Management Refactored Order Hnadling Major breaking changes * Pay Invoice button added as per Add a Show Invoice button to the seller in status Waiting-payment #49 * Cancel button should appear for relevant order states Button cancel in all screens in active status #42 * First cut of Mostro Chat * Updated Drawer Added Walkthrough Feature * Refdactored Data Storage and Notifiers * Updated Settings and Account Screens * add IT locale add IT locale translations arb file --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Francisco Calderón <[email protected]> Co-authored-by: devbtcp <[email protected]>
* added KeyManager class * Add key manager and related providers * added full privacy mode setting to app settings * Changed SecureStorageManager to SessionManager * Moved session storage/retrieval to SessionManager * Added separate wrap, seal and rumor functions * master key and trade key integration * minor edits * Minor fixes to session expiration * implementation of key manager features * verified sending new orders with full privacy * message and session serialization and retrieval * updated mostro message to handle cant-do * Implementation of order persistence between restarts * change order > content to order > payload * Initialize and load sessions at startup * Change rumor content to array * Debugging signing * Added support for cant-do * add buy/sell order now working * Update lib/data/models/cant_do.dart Fixes type Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * should fix #34 (review) * Update lib/features/take_order/screens/add_lightning_invoice_screen.dart Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * added localization extension for retrieving localized strings based on Action type and AbstractOrderNotifier to consolidate orders * Consolidate all OrderNotifiers as subclasses of AbstractOrderNotifier * minor changes to order notifier and notification notifiers * Filter user orders and updated Add Order screen to match web client * Added OrderBook feature * Added Drawer to Home Screen * Unifed order provider fixed * added Chat and Database support * Rationalised TakeOrderNotifier * removed bloc dependancy * Added integration and mocked unit tests * Integration tests for Create Sell Order * Added Key Management and Relay screens * Added extra key manager methods for importing existing key * Added rating feature * renamed order book and chat to trades and messages respectively * switch persistence to sembat and updated dart_nostr to latest version * updated mostro storage to use sembast * Clear caches * update tests * Added Mostro Instance Screen and updated OrderNotifier strings * Add QR Code Reader to Lightning Invoice screen * Separate our Lightning invoice components to widgets * Consolidated Drawer Screens * Order Screens complete * Updated launch icons * Major revisions * Changes to startup and added web support * Added public test nostr relay and daemon as default * set permissions for secure storage * UX clean up * Add mostro pubkey filter getting events * fixed privacy mode * added default relay * Updated Settings Screen * update build workflow * More buildflow fixes * Updated Take Order Screen and Home Screen Order List * improve Lightning Invoice Screen * Improve images * Add currency flag to my trades widget * Fix alignment on currency flag * Fix take order bug * fix for build action * works in full privacy mode * refactored app settings to be more reactive * More settings refactoring * Modified signing function * start of mostro service refactor * Refactored Mostro Service Updated My Trades Detail Screens Added 'Fiat Sent' and 'Release' buttons to My Trades Detail Screens Refactored Order Providers Added Mobile App Version and Git Hash to About Screen * Fixes error creating new order with ln address #38 Updated release build script Updated dependencies * Addresses When creating a new identity, the orders from the previous identity are not forgotten #36 * Started ChatRoom refactor Updated Action and CantDo enums Updated CantDo and Action string suggestions * Updated i10n strings to latest suggestions Included separate CantDo strings in i10n Added MostroMessageDetail widget to TradeDetailScreen * Implementation of Rate Counterpart * Partial implementation of Increment trade index only on success #35 * Changed AddLightingForm to back to the Home Screen on back/close * Revert Increment trade index only on success #35 fix * Major refactor of MostroService including deprecation of MostroRepository All MostroRepoistory in memory persistence operations are now embedded in MostroStorage which is now a direct dependency of MostroService * Added BaseStorage abstract class Refactored Session Management Refactored Order Hnadling Major breaking changes * Pay Invoice button added as per Add a Show Invoice button to the seller in status Waiting-payment #49 * Cancel button should appear for relevant order states Button cancel in all screens in active status #42 * First cut of Mostro Chat * Updated Drawer Added Walkthrough Feature * Refdactored Data Storage and Notifiers * Updated Settings and Account Screens * add IT locale add IT locale translations arb file * added background services * Added changes to background interface and upgraded MacOS settings * synchronize background services * Now uses two separate databases * ensure NostrService init * Rebuild of out of date annotated classes * add isRunning property to BackgroundService * Remove extra event call * Add lifecycle manager and refactor background service database paths * Revert MostrService and ChatRoomNotifier to subscribing directly in the foreground * Set background services to only run on app suspend * Startup modifications * Refactored background service * Replace route builders with pageBuilder to add fade transitions between screens * Added isRunning callback * renamed notification icon * Add background service capabilities and persistent notifications for iOS/Android * Mo background changes * Avoid race conditions when app is backgrounded * Add logging and improve app state transitions between foreground/background * Add NostrResponsiveButton widget and refactor order repository reload logic * Add async state handling and refresh functionality to trades screen * Refactor buttons using NostrResponsiveButton and improve state management for trade actions * Refactor message handling to use Sembast storage streams instead of EventBus * Add stream providers and watch methods for sessions and messages * Refactor storage and session providers, add error handling and remove unused code * Add auto-reset to button and improve order request ID generation for uniqueness * Fix order stream to emit cached events immediately and handle empty states * Refactor storage repositories to use base class and improve message handling * Add FSM-based order status tracking and update UI to use canonical status provider * Refactor message stream to use watchAllMessages and emit latest message * More refactoring of MostroStorage * Modified status source in TradesDetailScreen and MostroMessageDetailWidget * Change Lifecycle to mobile only and Modify MostroStorage * Separated events and orders databases into separate files to prevent race conditions between the main and background isolates * Fix order not saving pubkeys when serialized * Refactor message storage and retrieval to use latest messages consistently * Fix message watching and improve order notifier initialization * Add TradeState model and providers to manage trade status and actions * Cleanup TradeDetailScreen * Convert FutureProvider to StreamProvider for real-time order updates * Make mostroService and eventStorage providers keepAlive and remove cancel action handling * Add dispose logic for order notifiers and handle order cancellation cleanup * Refactor NostrResponsiveButton to use direct action/orderId instead of state providers * Rename NostrResponsiveButton to MostroReactiveButton and update references * Fix chat message deduplication and add sorting by creation timestamp * Add notification permissions and enhance notification settings for Android/iOS * Simplify reloadData by removing event clearing and empty list emission * Improve chat reliability and add event persistence with lifecycle management * Replace event provider with mostro storage and remove duplicate event check * Only request notifications on Android and filter sessions newer than 48 hours * Only subscribe to sessions created within the last 24 hours * Refactor session updates and add terminal status checks for active orders * Refactor button styles and remove hardcoded dimensions from reactive buttons * Filter chats older than 36h and fix session orderId update logic * Fix order notifier disposal and add Italian localization * Refactor background service and storage management; remove unused repositories and improve button functionality * Refactor notification handling, improve order update logic, and enhance button customization * Refactor notification service to use a single instance of FlutterLocalNotificationsPlugin and update MostroReactiveButton styles to use outlined and text button themes; remove unused rxdart dependency --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> Co-authored-by: Francisco Calderón <[email protected]> Co-authored-by: devbtcp <[email protected]>

This pull request implements key management as per the Mostro protocol specification.
An identity key is generated from a mnemonic when the user first opens the client and ephemeral trade keys are derived and used for each action.
Both identity and full privacy mode are implemented but identity mode is currently hard coded as the mostro daemon panics when attempting to unwrap a message with a null signature (see MostroP2P/mostro#414).
This PR also implements session management, with the identity key and details of each order stored using the secure storage mechanism of the respective platform between app restarts.
This PR also includes an initial implementation of the
cant-domessage type, with errors displayed to the user.There is currently no mechanism to reset the user keys but this will be implemented in a forthcoming PR once the UX is finalized.
This PR has been tested against the current mostro daemon code base but there will still be edge cases that could cause issues with making and taking orders.
Summary by CodeRabbit
Based on the comprehensive summary of changes, here are the updated release notes:
New Features
OrderNotifierfor managing order state and updates.Bug Fixes
Refactoring
Security Improvements