Skip to content

feat(bond): support Phase 1.5 anti-abuse bond invoice flow#592

Merged
grunch merged 7 commits into
mainfrom
bond-phase1
May 14, 2026
Merged

feat(bond): support Phase 1.5 anti-abuse bond invoice flow#592
grunch merged 7 commits into
mainfrom
bond-phase1

Conversation

@Catrya
Copy link
Copy Markdown
Member

@Catrya Catrya commented May 11, 2026

Adds the full mobile UX for the anti-abuse deposit (bond) that the taker must pay before continuing with a trade. The taker locks a Lightning hold invoice as a deposit; it is released when the trade finishes correctly.

What's included

  • New /pay_bond/<orderId> screen shown when the deposit invoice arrives, with:
    • Educational text explaining what the deposit is and what happens to the sats
    • QR with the deposit invoice
    • Copy / Share / Cancel buttons (Cancel asks for confirmation)
  • Automatic routing: when the deposit invoice arrives, the user is navigated to the bond screen
  • Entry point from Trade Detail: if the user leaves the bond screen without paying, opening the order from My Trades shows a brief message and a "Pay deposit" button that takes them back to the bond screen
  • "Awaiting deposit payment" status label in the My Trades list and Trade Detail header
  • Notification handling: tapping a deposit notification opens the bond screen
  • Session restore: orders restored in the deposit-waiting state are routed correctly
  • Localization: new keys for English, Spanish and Italian (German and French use English placeholders for now)

Test plan

  • Take an order that requires a deposit → bond screen opens with explanation, QR and buttons
  • Pay the deposit → user is routed to the next step (hold invoice or add-invoice depending on role)
  • Leave the bond screen and re-open the order from My Trades → "Pay deposit" button appears, navigates back to
    /pay_bond/
  • Cancel from either entry point → confirmation dialog, order is cancelled
  • Take an order that does not require a deposit → no regressions
  • My Trades list shows "Awaiting deposit payment" status correctly

Summary by CodeRabbit

  • New Features

    • Added a bond (anti-abuse deposit) payment screen showing a QR invoice with copy, share, and cancel actions.
    • Trade and order views now surface a “Pay bond” action where applicable.
    • Notifications now link directly to the bond payment flow.
  • Status / Flow

    • New order status for tracking awaiting bond payment and updated order state handling.
  • Localization

    • Added English, German, Spanish, French, and Italian strings for the bond flow.

Review Change Stack

Catrya added 2 commits May 11, 2026 14:12
  - New PayBondInvoiceScreen at /pay_bond/:orderId with explanatory text, invoice QR, copy/share buttons and cancel confirmation dialog
  - Route handling in AbstractMostroNotifier for the new action
  - Status label Awaiting deposit payment in trades list
  - New l10n keys in en/es/it (de/fr use English placeholders)
  - Notification mapper and restore manager updated to satisfy exhaustive-switch requirements
  - actions map: Status.waitingTakerBond exposes payBondInvoice, cancel, for both buyer and seller roles
  - MostroMessageDetail: localized message and status label for the bond waiting state
  - Trade detail switch: render Pay deposit button navigating to pay_bond, and use the bond-specific
  confirmer dialog when cancelling from the bond waiting state
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 11, 2026

Walkthrough

Adds a bond (anti-abuse deposit) payment flow: new enums Action.payBondInvoice and Status.waitingTakerBond, PayBondInvoiceScreen with QR/copy/share/cancel, /pay_bond/:orderId route, event handling, state-machine updates, notification/trade UI wiring, and i18n strings.

Changes

Bond Payment Feature

Layer / File(s) Summary
Data Models
lib/data/models/enums/action.dart, lib/data/models/enums/status.dart
New enum values: Action.payBondInvoice('pay-bond-invoice') and Status.waitingTakerBond('waiting-taker-bond').
Bond Screen
lib/features/order/screens/pay_bond_invoice_screen.dart
PayBondInvoiceScreen renders bond invoice QR, copy/share/cancel flows, Lightning URI launch fallback, error state, and reads order state.
Routing
lib/core/app_routes.dart
Adds /pay_bond/:orderId route rendering PayBondInvoiceScreen with orderId.
Order State Machine
lib/features/order/models/order_state.dart
Maps Action.payBondInvoiceStatus.waitingTakerBond and allows payBondInvoice/cancel in that state for buyer and seller.
Event Handling & Restore
lib/features/order/notifiers/abstract_mostro_notifier.dart, lib/features/restore/restore_manager.dart
Handles payBondInvoice events by saving session and navigating to /pay_bond/<id>; restore maps waiting status to the action.
Notifications
lib/features/notifications/utils/notification_message_mapper.dart, lib/features/notifications/widgets/notification_item.dart
Maps action to existing payment notification keys and routes taps to bond screen.
Trade UI
lib/features/trades/screens/trade_detail_screen.dart, lib/features/trades/widgets/mostro_message_detail_widget.dart, lib/features/trades/widgets/trades_list_item.dart
Adds "pay bond" button for sellers, localized action message, and waiting-themed status chip.
Localization
lib/l10n/intl_en.arb, lib/l10n/intl_de.arb, lib/l10n/intl_es.arb, lib/l10n/intl_fr.arb, lib/l10n/intl_it.arb
Adds bond screen title, explanation, pay-invoice prompt, waiting status label, and pay-button/message keys across languages.

Sequence Diagram(s)

sequenceDiagram
  participant MostroEvent
  participant AbstractMostroNotifier
  participant SessionNotifier
  participant GoRouter
  participant PayBondInvoiceScreen

  MostroEvent->>AbstractMostroNotifier: receive Action.payBondInvoice (PaymentRequest)
  AbstractMostroNotifier->>SessionNotifier: sessionNotifier.saveSession(session)
  AbstractMostroNotifier->>GoRouter: navigate('/pay_bond/<event.id>')
  GoRouter->>PayBondInvoiceScreen: build(orderId)
  PayBondInvoiceScreen->>PayBondInvoiceScreen: render QR, enable copy/share/cancel
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • AndreaDiazCorreia
  • grunch
  • BraCR10

Poem

🐰 A tiny rabbit hops the code,
A bond invoice, bright and bold,
QR beacons, copy, share —
Lightning hums through careful care,
Trades wait patient, trust upheld.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately and specifically describes the main feature being added: support for a Phase 1.5 anti-abuse bond invoice flow, which matches the comprehensive changes across routing, state management, UI screens, and localization.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch bond-phase1

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

Copy link
Copy Markdown
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

🧹 Nitpick comments (1)
lib/features/notifications/utils/notification_message_mapper.dart (1)

20-21: ⚡ Quick win

Use bond-specific notification keys for payBondInvoice.

Right now bond deposit prompts reuse the generic “payment required” copy, which can blur the distinction between normal invoice payment and anti-abuse deposit payment. A dedicated title/message pair would make the notification intent clearer.

💡 Suggested mapping refinement
-      case mostro.Action.payInvoice:
-      case mostro.Action.payBondInvoice:
+      case mostro.Action.payInvoice:
         return 'notification_payment_required_title';
+      case mostro.Action.payBondInvoice:
+        return 'notification_bond_payment_required_title';
-      case mostro.Action.payInvoice:
-      case mostro.Action.payBondInvoice:
+      case mostro.Action.payInvoice:
         return 'notification_payment_required_message';
+      case mostro.Action.payBondInvoice:
+        return 'notification_bond_payment_required_message';

Also add corresponding ARB keys for all supported locales.

Also applies to: 123-124

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@lib/features/notifications/utils/notification_message_mapper.dart` around
lines 20 - 21, The mapping for mostro.Action.payBondInvoice currently returns
the generic 'notification_payment_required_title'; change this to a
bond-specific key (e.g., 'notification_bond_payment_required_title') in the
notification mapping function (where mostro.Action.payBondInvoice is handled)
and update any other payBondInvoice-related returns in the same mapper (the
other occurrence mentioned) to use corresponding bond-specific title/message
keys (e.g., 'notification_bond_payment_required_message'); then add the new ARB
keys and translations for all supported locales so the new bond-specific
title/message are available in the app.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/features/order/screens/pay_bond_invoice_screen.dart`:
- Around line 118-123: The QR widget is rendered even when lnInvoice is empty,
producing a confusing blank QR; update the build logic around QrImageView to
conditionally render a placeholder/loading state (e.g., a spinner, message, or
empty-state widget) whenever lnInvoice is null or an empty string instead of
passing it into QrImageView, and only create QrImageView with data: lnInvoice
when lnInvoice.isNotEmpty; adjust related errorStateBuilder if needed to handle
real QR errors separately.
- Around line 57-59: The navigation happens before the cancellation completes;
change the sequence so you call and await orderNotifier.cancelOrder() first and
only call context.go('/') after it succeeds; wrap the await
orderNotifier.cancelOrder() in a try/catch (or handle the returned result) to
detect failure and show an error (e.g., via ScaffoldMessenger or the notifier's
error state) instead of navigating; update the code around
orderNotifierProvider(orderId).notifier, cancelOrder(), and context.go('/')
accordingly.

---

Nitpick comments:
In `@lib/features/notifications/utils/notification_message_mapper.dart`:
- Around line 20-21: The mapping for mostro.Action.payBondInvoice currently
returns the generic 'notification_payment_required_title'; change this to a
bond-specific key (e.g., 'notification_bond_payment_required_title') in the
notification mapping function (where mostro.Action.payBondInvoice is handled)
and update any other payBondInvoice-related returns in the same mapper (the
other occurrence mentioned) to use corresponding bond-specific title/message
keys (e.g., 'notification_bond_payment_required_message'); then add the new ARB
keys and translations for all supported locales so the new bond-specific
title/message are available in the app.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 713ad311-f306-4fb3-80e4-b710762aa494

📥 Commits

Reviewing files that changed from the base of the PR and between b8bbee9 and a28dfe8.

📒 Files selected for processing (17)
  • lib/core/app_routes.dart
  • lib/data/models/enums/action.dart
  • lib/data/models/enums/status.dart
  • lib/features/notifications/utils/notification_message_mapper.dart
  • lib/features/notifications/widgets/notification_item.dart
  • lib/features/order/models/order_state.dart
  • lib/features/order/notifiers/abstract_mostro_notifier.dart
  • lib/features/order/screens/pay_bond_invoice_screen.dart
  • lib/features/restore/restore_manager.dart
  • lib/features/trades/screens/trade_detail_screen.dart
  • lib/features/trades/widgets/mostro_message_detail_widget.dart
  • lib/features/trades/widgets/trades_list_item.dart
  • lib/l10n/intl_de.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_fr.arb
  • lib/l10n/intl_it.arb

Comment thread lib/features/order/screens/pay_bond_invoice_screen.dart
Comment thread lib/features/order/screens/pay_bond_invoice_screen.dart Outdated
mostronatorcoder[bot]
mostronatorcoder Bot previously approved these changes May 12, 2026
Copy link
Copy Markdown
Contributor

@mostronatorcoder mostronatorcoder Bot left a comment

Choose a reason for hiding this comment

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

I reviewed the PR and also checked the existing review discussion before deciding. The previously raised concern about optimistic navigation on cancel is not a blocker here, because Catrya already clarified that this mirrors the existing app-wide cancellation pattern and failures are surfaced asynchronously through the existing cant-do flow. That is a broader architectural cleanup, not something this PR should be forced to solve in isolation.

On the actual change set, the implementation is coherent and matches the Phase 1.5 bond flow well:

  • Action.payBondInvoice and Status.waitingTakerBond are integrated consistently through routing, notification handling, restore, trade detail, and trades list presentation.
  • The new /pay_bond/:orderId screen covers the key UX actions: explanation, QR, copy, share, and cancel confirmation.
  • OrderState exposes the correct action set for waitingTakerBond for both roles, which keeps the FSM explicit instead of relying on ad-hoc UI conditionals.
  • Restore support is present, so reopened sessions can land back in the bond flow correctly.
  • CI is green.

I do not see a correctness issue here that should block merge. The remaining CodeRabbit points are either copy-level refinements or follow-up polish, not merge blockers for this phase. Approved.

grunch
grunch previously approved these changes May 14, 2026
Copy link
Copy Markdown
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

@Catrya Catrya dismissed stale reviews from grunch and mostronatorcoder[bot] via fb75c27 May 14, 2026 19:30
Copy link
Copy Markdown
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

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@lib/l10n/intl_de.arb`:
- Line 709: The ARB entry "bondPayInvoicePrompt" uses the placeholder {amount}
but lacks the required metadata block; add an `@bondPayInvoicePrompt` metadata
object immediately after the key that defines the "amount" placeholder (include
a brief "description" and a "placeholders" entry specifying "amount" with an
appropriate type/example, e.g., numeric/sats), so Flutter's localization tooling
recognizes the placeholder.

In `@lib/l10n/intl_en.arb`:
- Line 709: The new localization key "bondPayInvoicePrompt" includes a
placeholder {amount} but lacks the required metadata entry
(`@bondPayInvoicePrompt`) describing that placeholder; add an
`@bondPayInvoicePrompt` metadata block (with "description" and "placeholders"
mapping for "amount" and a sample "type" or "example") to intl_en.arb and then
add the equivalent key+metadata entries to intl_es.arb and intl_it.arb (keeping
the same placeholder name {amount}) so all three ARB files stay in sync;
reference the key "bondPayInvoicePrompt" and the metadata marker
"@bondPayInvoicePrompt" when making the changes.

In `@lib/l10n/intl_es.arb`:
- Line 622: Add the missing placeholder metadata for the localization key
bondPayInvoicePrompt by adding an accompanying `@bondPayInvoicePrompt` entry that
declares the {amount} placeholder (e.g., "placeholders": {"amount":
{"type":"String"}} and a short "description") in intl_es.arb; also add the same
key and metadata to intl_en.arb and intl_it.arb so all three ARB files contain
the new localized key and its placeholder metadata.

In `@lib/l10n/intl_fr.arb`:
- Around line 707-712: The FR ARB entries (bondScreenTitle, bondExplanation,
bondPayInvoicePrompt, statusWaitingTakerBond, payBondMessage, payBondButton) are
English; replace each value with accurate French translations so the French
locale contains localized user-facing text (or if translations are unavailable,
revert these keys to the default locale and open a tracking issue to add proper
French strings before release); update the six keys consistently and ensure
punctuation/newlines in bondExplanation are preserved in the translated string.
- Line 709: The ARB entry "bondPayInvoicePrompt" contains a placeholder {amount}
but lacks the required metadata block; add an `@bondPayInvoicePrompt` metadata
object that defines the placeholder "amount" (e.g., include a "placeholders" map
with "amount" and supply a "type" like "String" or "int" and a brief
"description") so the localization tooling knows about the parameter. Ensure the
metadata key is exactly `@bondPayInvoicePrompt` and that it documents the "amount"
placeholder type and purpose.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f2c33af4-e40c-497a-8c11-266032550de0

📥 Commits

Reviewing files that changed from the base of the PR and between a28dfe8 and fb75c27.

📒 Files selected for processing (6)
  • lib/features/order/screens/pay_bond_invoice_screen.dart
  • lib/l10n/intl_de.arb
  • lib/l10n/intl_en.arb
  • lib/l10n/intl_es.arb
  • lib/l10n/intl_fr.arb
  • lib/l10n/intl_it.arb
✅ Files skipped from review due to trivial changes (1)
  • lib/l10n/intl_it.arb
🚧 Files skipped from review as they are similar to previous changes (1)
  • lib/features/order/screens/pay_bond_invoice_screen.dart

Comment thread lib/l10n/intl_de.arb
Comment thread lib/l10n/intl_en.arb
Comment thread lib/l10n/intl_es.arb
Comment thread lib/l10n/intl_fr.arb
Comment thread lib/l10n/intl_fr.arb
Copy link
Copy Markdown
Contributor

@mostronatorcoder mostronatorcoder Bot left a comment

Choose a reason for hiding this comment

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

I re-reviewed the latest revision of this PR against the new commits and the current review discussion. I do not see a new correctness issue introduced by the latest changes.

The recent CodeRabbit comments do not change my conclusion:

  • The placeholder metadata blocks for bondPayInvoicePrompt are optional in Flutter gen-l10n, and the existing project already uses placeholder keys without metadata. That is a style/consistency cleanup topic, not a merge blocker for this PR.
  • The English fallback strings in de and fr are explicitly part of the scoped approach described by the author for these bond keys, and I do not think this should block the functional Phase 1.5 flow.

On the implementation itself, the PR still looks coherent:

  • waitingTakerBond / payBondInvoice are integrated consistently across routing, notifier handling, restore mapping, trades list, trade detail, and message detail.
  • The new bond screen now includes the prompt string with the invoice amount, which improves clarity for the taker flow.
  • CI is green.

Given the current scope and the discussion already captured on the PR, I approve the latest revision.

@grunch grunch merged commit 35a544a into main May 14, 2026
2 checks passed
@grunch grunch deleted the bond-phase1 branch May 14, 2026 21:52
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.

2 participants