Skip to content

Feat: antiabuse bond enabled and bond slash activation in admin finalization#79

Merged
arkanoider merged 5 commits into
mainfrom
feat/bond-enabled-add-bond-invoice
May 24, 2026
Merged

Feat: antiabuse bond enabled and bond slash activation in admin finalization#79
arkanoider merged 5 commits into
mainfrom
feat/bond-enabled-add-bond-invoice

Conversation

@arkanoider
Copy link
Copy Markdown
Collaborator

@arkanoider arkanoider commented May 23, 2026

Summary

  • Instance bond_enabled (kind 38385): Bond slash button and confirm recap only when Mostro advertises bond_enabled: true (mostro_info.rs).
  • Trader AddBondInvoice: Bond payout invoice popup and execute_add_bond_invoice flow (aligned with existing AddInvoice patterns).
  • Admin finalize wait/response: execute_admin_settle / execute_admin_cancel send with request_id, wait_for_dm, and handle_mostro_responseCantDo (e.g. invalid bond slash) returns an error before updating admin_disputes.
  • Finalize popup UX: Action button bodies show Admin settle / Admin cancel (titles remain 💰 Pay buyer / ↩️ Refund seller).
  • Success popup: Multi-line BondSlashChoice::finalize_success_message with word-boundary wrapping in operation_result.rs.

Motivation

Mostro can reject admin finalize with CantDo; previously Mostrix updated local state after send-only. Long UUIDs also broke the success toast mid-word.

Summary by CodeRabbit

  • New Features

    • Admin dispute finalization now includes optional bond-slash actions when anti-abuse bonds are enabled.
    • Added bond payout invoice notifications for traders after dispute finalization.
    • Display "Anti-abuse bonds" enablement status in Mostro daemon information.
  • Bug Fixes

    • Improved finalized dispute UI—action buttons now properly disabled with em-dash placeholder instead of "N/A".
  • Documentation

    • Updated admin dispute finalization flow and bond-slash behavior documentation.

Review Change Stack

arkanoider and others added 2 commits May 19, 2026 23:44
…nvoice.

Parse bond_enabled from kind-38385 instance info to hide the finalize Bond button when bonds are off. Wire trader AddBondInvoice notifications with invoice input, execute_add_bond_invoice, and updated docs.

Co-authored-by: Cursor <cursoragent@cursor.com>
Admin settle/cancel now use request_id, wait_for_dm, and
handle_mostro_response so CantDo errors surface before DB updates.
Finalize popup shows Admin settle/cancel inside action buttons;
success popup uses a structured multi-line message with word wrap.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 23, 2026

Walkthrough

This PR implements complete anti-abuse bond support: instance-level bond capability detection, admin dispute finalization with conditional bond-slash UI and DM request/response execution, trader-side bond-payout invoice popups with async submission, and dynamic operation-result message rendering with proper text wrapping.

Changes

Anti-abuse bond finalization and payout support

Layer / File(s) Summary
Mostro instance bond capability detection
src/util/mostro_info.rs, src/util/mod.rs
MostroInstanceInfo gains bond_enabled: Option<bool> field parsed from kind-38385 tags. New instance_bonds_enabled() helper returns true only when explicitly enabled. Tests cover parsing and gating behavior.
Admin finalize DM request/response execution
src/util/order_utils/execute_admin_settle.rs, execute_admin_cancel.rs, helper.rs
Both settle/cancel now generate unique request_id, construct dispute messages using that correlation ID, send via shared DM utilities, await response with 15s timeout, validate sender pubkey and response action, and persist changes only after confirmation. DM response validation extended to allow AddBondInvoice null request_id.
Bond success message formatting and finalize handler
src/util/order_utils/bond_resolution.rs, src/ui/key_handler/admin_handlers.rs
BondSlashChoice::finalize_success_message() formats multi-line success toast with settle/cancel outcome and bond-choice label. execute_finalize_dispute_action uses new helper instead of inline construction.
Bond-conditional finalize popup and confirm UI
src/ui/dispute_finalization_popup.rs, dispute_finalization_confirm.rs, key_handler/chat_helpers.rs
render_finalization_popup and render_action_buttons compute bond_ui_enabled flag and adapt layout: 3 columns (with Bond button) when enabled, 2 columns when disabled. render_finalization_confirm builds dynamic vertical constraints, conditionally includes bond recap section. FinalizeDisputePopupButton::from_index maps index 2 to BondSlash only when bond UI enabled.
Finalize button cycling and Enter-key handling with bond gating
src/ui/key_handler/mod.rs, enter_handlers.rs
cycle_finalization_button refactored to compute max-button index from bond_ui_enabled, clamping navigation accordingly. Enter-key handler derives bond_ui_enabled from app.mostro_info, clamps selected_button_index when bond disabled, and passes flag to button-selection calls.
Dynamic multi-line operation result message rendering
src/ui/operation_result.rs
New wrap_message_lines helper splits and wraps text by paragraph and word boundaries (preserving long UUIDs). info_popup_height computes dynamic popup height from wrapped line count. OperationResult::Error/Info rendering switched from character-chunking to word-boundary wrapping.
Bond payout invoice action routing and submission
src/ui/key_handler/message_handlers.rs, mod.rs, enter_handlers.rs, src/util/dm_utils/mod.rs, notifications_ch_mng.rs, order_ch_mng.rs
Action::AddBondInvoice added to invoice-popup-action mapping and Enter dispatcher. New submit_add_bond_invoice() validates input, switches to waiting mode, spawns async execute_add_bond_invoice task, forwards follow-up results or emits InvoiceSubmitted on Ok(None). DM utilities (upsert, extraction, notification-gating, popup-routing) extended to recognize bond-payout invoices as actionable with focused input state.
Bond payout invoice popup and message notification UI
src/ui/message_notification.rs
New render_add_bond_invoice() renderer lays out sat_amount label, centered invoice input, yes/no buttons, and help text. render_message_notification sizes AddBondInvoice popups (width 90, height 21), maps title, and dispatches to new renderer.
Shared add-invoice/add-bond-invoice DM execution and result mapping
src/util/order_utils/execute_add_invoice.rs, mod.rs
Refactors add-invoice handling into internal execute_payment_request_reply (strict response validation) and new execute_bond_payment_request_reply (lenient, returns Ok(None) on timeout/empty DM). New payment_request_payload_for_invoice validates Lightning address reachability or unexpired BOLT11. Exports execute_add_bond_invoice() wrapper and reimplements execute_add_invoice() as thin delegator.
OperationResult::OpenInvoicePopup variant and order invoice gating
src/ui/orders.rs
Adds OperationResult::OpenInvoicePopup variant carrying MessageNotification + OrderMessage for synchronous popup application. Extends invoice_popup_allowed_for_order_status to block for Canceled/CanceledByAdmin. local_user_must_act_on_invoice_popup always requires action for AddBondInvoice. New bond_payout_notification_body helper formats slashed-at timestamp.
UiMode::OperationResult boxing refactor and mode constructor
src/ui/app_state.rs, src/main.rs, src/ui/key_handler/{admin_handlers,async_tasks,confirmation,enter_handlers,esc_handlers}.rs, src/util/dm_utils/order_ch_mng.rs
UiMode::OperationResult now stores Box<OperationResult>. New UiMode::operation_result(result) constructor standardizes mode creation. All UiMode::OperationResult(...) calls updated to lowercase constructor method across 50+ sites (error/info transitions, key reload, validation, admin mode, etc.).
Key handler clipboard/paste and navigation updates
src/ui/key_handler/mod.rs, order_ch_mng.rs
Clipboard paste fallback and shortcuts now activate for AddBondInvoice notifications alongside AddInvoice. Left/right navigation dispatch extended for bond-invoice actions. Multi-line reformatting of "do not overwrite" invoice action match in order_ch_mng.
Mostro info tab and main.rs dispute refresh markers
src/ui/tabs/mostro_info_tab.rs, src/main.rs
Mostro daemon info now displays "Anti-abuse bonds" row with enabled/disabled/unknown mapping from bond_enabled field. Main.rs is_dispute_related predicate updated to match "taken successfully" and "Dispute finalized" for dispute refresh.
Comprehensive documentation
README.md, docs/{ADMIN_DISPUTES,FINALIZE_DISPUTES,MESSAGE_FLOW_AND_PROTOCOL,TUI_INTERFACE,README}.md
Updated to describe bond-enabled gating, DM request/response flow with explicit request_id correlation, success message formatting with finalize_success_message(), bond-payout invoice auto-opening and submission, operation result dynamic text wrapping, and related execution paths with sequence diagrams.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related issues

Possibly related PRs

  • MostroP2P/mostrix#78 — Shares the admin Shift+F dispute-finalization UI refactor (render_finalization_popup, render_finalization_confirm, button cycling), with this PR extending it via instance-level bond_enabled gating.
  • MostroP2P/mostrix#77 — Continues admin dispute finalization by threading BondSlashChoice through finalize/settle/cancel execution (finalize_success_message, execute_admin_settle/cancel bond payload), building on prior foundation work.
  • MostroP2P/mostrix#76 — Introduces BondSlashChoice/payload/wire-format foundation; this PR implements and uses that foundation in admin UI/execute flows and trader payout path.

Suggested reviewers

  • grunch
  • Catrya
  • mostronatorcoder
  • AndreaDiazCorreia

🐰 A rabbit hops through bond slashes and invoices bright,
Where settle and cancel dance in the flickering light.
Dynamic wrapping, DM flows, and popups galore—
The payout path opens like never before!
bounces happily with freshly wrapped text

🚥 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 title accurately describes the main change: implementing anti-abuse bond enablement and bond slash activation in admin finalization, which is the primary focus of this PR across multiple files.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/bond-enabled-add-bond-invoice

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: 3

🧹 Nitpick comments (1)
src/ui/orders.rs (1)

365-370: ⚡ Quick win

Add focused unit tests for the new AddBondInvoice gating branches.

These branches decide popup eligibility and acting-party routing. A couple of targeted tests for invoice_popup_allowed_for_order_status and local_user_must_act_on_invoice_popup would lock this behavior and prevent regressions.

Also applies to: 392-392

🤖 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 `@src/ui/orders.rs` around lines 365 - 370, Add focused unit tests for the
AddBondInvoice gating logic: write tests for
invoice_popup_allowed_for_order_status and local_user_must_act_on_invoice_popup
that assert the popup is allowed for statuses other than Canceled and
CanceledByAdmin and disallowed for those two, and verify routing/acting-party
behavior (local user must act vs remote) for each relevant Status variant;
reference the Action::AddBondInvoice branch and the functions
invoice_popup_allowed_for_order_status and local_user_must_act_on_invoice_popup
when adding these targeted tests to prevent regressions.
🤖 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 `@src/util/order_utils/execute_add_invoice.rs`:
- Around line 87-99: The call to wait_for_dm currently returns an error on
timeout which causes AddBondInvoice flows to fail; change the logic around
wait_for_dm(&order_trade_keys, FETCH_EVENTS_TIMEOUT, sent_message).await so that
if it returns a timeout-style error you treat it like an acceptable no-response
for Action::AddBondInvoice (return Ok(())) and only propagate non-timeout
errors; keep the existing parse_dm_events(...) and messages.first() handling for
non-timeout successful receipts. Ensure you identify the timeout by matching the
error variant or message from wait_for_dm and reference wait_for_dm,
FETCH_EVENTS_TIMEOUT, sent_message, Action::AddBondInvoice, parse_dm_events, and
messages.first() in your change.

In `@src/util/order_utils/execute_admin_cancel.rs`:
- Around line 63-65: Remove the secret key derivation and logging: stop calling
admin_keys.secret_key() and delete the admin_keys_log variable and
log::info!("admin_keys dispute: {}", admin_keys_log); instead, if logging is
needed use a non-sensitive identifier such as
admin_keys.public_key().to_bech32() or an admin ID/alias; update any references
to admin_keys_log in this scope (in the execute_admin_cancel flow) accordingly
so no private key material is emitted to logs.

In `@src/util/order_utils/execute_take_dispute.rs`:
- Around line 63-65: Remove the secret-key exposure: do not call
admin_keys.secret_key() or log admin_keys_log in execute_take_dispute.rs;
instead log a non-sensitive identifier (e.g.,
admin_keys.public_key().to_bech32() or an admin_keys.id() / redacted
placeholder) and delete the log::info!("admin_keys dispute: {}", admin_keys_log)
line so secret material is never read or printed from the admin_keys value.

---

Nitpick comments:
In `@src/ui/orders.rs`:
- Around line 365-370: Add focused unit tests for the AddBondInvoice gating
logic: write tests for invoice_popup_allowed_for_order_status and
local_user_must_act_on_invoice_popup that assert the popup is allowed for
statuses other than Canceled and CanceledByAdmin and disallowed for those two,
and verify routing/acting-party behavior (local user must act vs remote) for
each relevant Status variant; reference the Action::AddBondInvoice branch and
the functions invoice_popup_allowed_for_order_status and
local_user_must_act_on_invoice_popup when adding these targeted tests to prevent
regressions.
🪄 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: ea7fd460-1d85-460c-9d8d-9c285c798aea

📥 Commits

Reviewing files that changed from the base of the PR and between 6cb4481 and 53419dc.

📒 Files selected for processing (30)
  • README.md
  • docs/ADMIN_DISPUTES.md
  • docs/FINALIZE_DISPUTES.md
  • docs/MESSAGE_FLOW_AND_PROTOCOL.md
  • docs/README.md
  • docs/TUI_INTERFACE.md
  • src/main.rs
  • src/ui/dispute_finalization_confirm.rs
  • src/ui/dispute_finalization_popup.rs
  • src/ui/key_handler/admin_handlers.rs
  • src/ui/key_handler/chat_helpers.rs
  • src/ui/key_handler/enter_handlers.rs
  • src/ui/key_handler/message_handlers.rs
  • src/ui/key_handler/mod.rs
  • src/ui/message_notification.rs
  • src/ui/operation_result.rs
  • src/ui/orders.rs
  • src/ui/tabs/mostro_info_tab.rs
  • src/util/dm_utils/mod.rs
  • src/util/dm_utils/notifications_ch_mng.rs
  • src/util/dm_utils/order_ch_mng.rs
  • src/util/mod.rs
  • src/util/mostro_info.rs
  • src/util/order_utils/bond_resolution.rs
  • src/util/order_utils/execute_add_invoice.rs
  • src/util/order_utils/execute_admin_cancel.rs
  • src/util/order_utils/execute_admin_settle.rs
  • src/util/order_utils/execute_take_dispute.rs
  • src/util/order_utils/helper.rs
  • src/util/order_utils/mod.rs

Comment thread src/util/order_utils/execute_add_invoice.rs
Comment thread src/util/order_utils/execute_admin_cancel.rs Outdated
Comment thread src/util/order_utils/execute_take_dispute.rs Outdated
Copy link
Copy Markdown

@ermeme ermeme Bot left a comment

Choose a reason for hiding this comment

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

Hermes Agent Review

Verdict: Request changes

Critical

  • admin_keys.secret_key() is being converted to bech32 and written to application logs in execute_take_dispute.rs and execute_admin_cancel.rs. That leaks the admin private key into logs. Please remove those log lines and log only non-sensitive identifiers.

Warning

  • The AddBondInvoice branch in execute_add_invoice.rs returns success even when Mostro sends no follow-up DM, and it also returns Ok(()) for any response that passes handle_mostro_response without checking the expected success action. That can report "Bond payout invoice sent successfully" for a silent failure or a wrong-action reply. Please keep timeout as an error and validate the expected success action before returning success.

Comment thread src/util/order_utils/execute_take_dispute.rs Outdated
Comment thread src/util/order_utils/execute_admin_cancel.rs Outdated
Comment thread src/util/order_utils/execute_add_invoice.rs Outdated
Copy link
Copy Markdown

@ermeme ermeme Bot left a comment

Choose a reason for hiding this comment

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

Hermes Agent Review

Verdict: Approve

I re-checked the latest head (ccff795) and the earlier blockers are resolved:

  • The admin private key is no longer being logged.
  • AdminSettle / AdminCancel now wait for and validate the Mostro response before updating local state.
  • The bond payout flow is wired through the UI and DM handlers cleanly.

I also ran the test suite locally: 90 passed, 0 failed.

Nice cleanup.

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 found a blocker in the new AddBondInvoice execution path.

execute_payment_request_reply() is still strict for AddInvoice, but for AddBondInvoice it now returns Ok(()) in all of these cases:

  • wait_for_dm(...) times out
  • no parsed response message is found
  • any parsed response passes handle_mostro_response(...), regardless of the returned action

That last part is the real problem:

let inner_message = handle_mostro_response(response_message, request_id)?;

if action == Action::AddBondInvoice {
    return Ok(());
}

So AddBondInvoice currently treats every request-id-matching non-CantDo reply as success, without checking that Mostro actually acknowledged the bond payout invoice with the expected action.

This is looser than the existing AddInvoice path and can produce a false local success state if:

  • Mostro replies with an unexpected action
  • the wrong phase message is matched first
  • or the daemon behavior changes and still sends a request-id-matching response that is not the intended confirmation

I am also not fully comfortable with treating both timeout and empty-response as unconditional success for this path, but even setting that aside, the missing action validation is enough to block for me.

I think AddBondInvoice needs the same kind of explicit response contract that AddInvoice and the updated admin finalize flows now use: accept only the expected acknowledgement action(s), and fail otherwise.

Because this can incorrectly report success for a bond payout invoice that was not actually confirmed the way the client expects, I am marking this as request changes.

After bond payout bolt11, wait_for_dm and map Mostro follow-ups
(e.g. WaitingBuyerInvoice, PayBondInvoice) to OpenInvoicePopup or
PaymentRequestRequired instead of stopping at a success toast. Treat
DM timeout as acceptance for AddBondInvoice only. Document the flow;
box large OperationResult payloads to satisfy clippy.

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

Reviewed the new commit. The blocker is addressed.

The AddBondInvoice path is now fully separated from the generic execute_payment_request_reply and lives in its own execute_bond_payment_request_reply. The timeout and empty-response cases now return Ok(None) with a descriptive log instead of a silent Ok(()), and any real response from Mostro goes through handle_mostro_response first and then through the action match in operation_result_from_bond_invoice_reply. So the path is no longer unconditionally successful regardless of what Mostro replies.

The response contract is explicit now: known follow-up actions chain into the next UI step; anything else logs and returns None rather than failing hard, which is a reasonable choice while the protocol is still being defined. That is exactly the kind of defensiveness I was asking for.

No remaining blocker from my side.

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.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/ui/operation_result.rs (1)

21-33: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Handle overlong single tokens in wrapper to avoid clipped content.

Current wrapping only breaks on whitespace. Long tokens (e.g., UUIDs / bolt11) can exceed width, get visually clipped, and make info_popup_height underestimate space.

💡 Proposed fix
 fn wrap_message_lines(message: &str, width: usize) -> Vec<Line<'static>> {
     let wrap_width = width.max(10);
     let mut lines = Vec::new();
@@
         let mut current = String::new();
         for word in paragraph.split_whitespace() {
+            // Fallback for overlong single tokens (UUIDs, invoices, etc.).
+            if word.len() > wrap_width {
+                if !current.is_empty() {
+                    lines.push(Line::from(std::mem::take(&mut current)));
+                }
+                let mut chunk = String::new();
+                for ch in word.chars() {
+                    chunk.push(ch);
+                    if chunk.len() >= wrap_width {
+                        lines.push(Line::from(std::mem::take(&mut chunk)));
+                    }
+                }
+                if !chunk.is_empty() {
+                    current = chunk;
+                }
+                continue;
+            }
             if current.is_empty() {
                 current = word.to_string();
             } else if current.len() + 1 + word.len() <= wrap_width {
                 current.push(' ');
                 current.push_str(word);

Also applies to: 42-44, 193-194, 216-217

🤖 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 `@src/ui/operation_result.rs` around lines 21 - 33, The current word-wrapping
loop in src/ui/operation_result.rs (uses variables paragraph, current,
wrap_width, lines and constructs Line::from) only breaks at whitespace, so
single tokens longer than wrap_width get clipped; modify the loop to detect when
a token's length > wrap_width and split that token into wrap_width-sized chunks
(appending the first chunk to current or as its own Line::from if current is
empty, and pushing subsequent chunks as separate lines), and when adding a chunk
to a non-empty current ensure proper spacing/transition using
std::mem::take(&mut current); apply the same chunking logic to the other wrap
sites referenced (the similar blocks around lines noted in the comment) so
overlong tokens are split rather than overflowing.
🧹 Nitpick comments (1)
src/util/order_utils/execute_add_invoice.rs (1)

19-22: ⚡ Quick win

Make timeout detection less brittle than full-string equality.

Matching the entire error string risks breaking timeout tolerance on tiny message wording changes.

💡 Proposed fix
 fn is_wait_for_dm_timeout(err: &anyhow::Error) -> bool {
-    err.to_string() == "Timeout waiting for DM or gift wrap event"
+    err.to_string().contains("Timeout waiting for DM")
 }
🤖 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 `@src/util/order_utils/execute_add_invoice.rs` around lines 19 - 22, The
current is_wait_for_dm_timeout function is brittle because it compares the whole
error string; change it to robustly detect timeout by checking the error chain
for a matching substring or cause instead — e.g., update
is_wait_for_dm_timeout(err: &anyhow::Error) to return true if
err.chain().any(|e| e.to_string().contains("Timeout waiting for DM")) (or use
starts_with/contains for a stable prefix like "Timeout waiting for DM") so small
wording changes won't break detection.
🤖 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.

Outside diff comments:
In `@src/ui/operation_result.rs`:
- Around line 21-33: The current word-wrapping loop in
src/ui/operation_result.rs (uses variables paragraph, current, wrap_width, lines
and constructs Line::from) only breaks at whitespace, so single tokens longer
than wrap_width get clipped; modify the loop to detect when a token's length >
wrap_width and split that token into wrap_width-sized chunks (appending the
first chunk to current or as its own Line::from if current is empty, and pushing
subsequent chunks as separate lines), and when adding a chunk to a non-empty
current ensure proper spacing/transition using std::mem::take(&mut current);
apply the same chunking logic to the other wrap sites referenced (the similar
blocks around lines noted in the comment) so overlong tokens are split rather
than overflowing.

---

Nitpick comments:
In `@src/util/order_utils/execute_add_invoice.rs`:
- Around line 19-22: The current is_wait_for_dm_timeout function is brittle
because it compares the whole error string; change it to robustly detect timeout
by checking the error chain for a matching substring or cause instead — e.g.,
update is_wait_for_dm_timeout(err: &anyhow::Error) to return true if
err.chain().any(|e| e.to_string().contains("Timeout waiting for DM")) (or use
starts_with/contains for a stable prefix like "Timeout waiting for DM") so small
wording changes won't break detection.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e90bbd03-75e8-4ff8-92c1-dbd637e0c6e5

📥 Commits

Reviewing files that changed from the base of the PR and between 53419dc and 4daa1b2.

📒 Files selected for processing (19)
  • docs/FINALIZE_DISPUTES.md
  • docs/MESSAGE_FLOW_AND_PROTOCOL.md
  • docs/README.md
  • docs/TUI_INTERFACE.md
  • src/main.rs
  • src/ui/app_state.rs
  • src/ui/key_handler/admin_handlers.rs
  • src/ui/key_handler/async_tasks.rs
  • src/ui/key_handler/confirmation.rs
  • src/ui/key_handler/enter_handlers.rs
  • src/ui/key_handler/esc_handlers.rs
  • src/ui/key_handler/message_handlers.rs
  • src/ui/key_handler/mod.rs
  • src/ui/operation_result.rs
  • src/ui/orders.rs
  • src/util/dm_utils/notifications_ch_mng.rs
  • src/util/dm_utils/order_ch_mng.rs
  • src/util/order_utils/execute_add_invoice.rs
  • src/util/order_utils/execute_admin_cancel.rs
💤 Files with no reviewable changes (1)
  • src/util/order_utils/execute_admin_cancel.rs
✅ Files skipped from review due to trivial changes (3)
  • docs/README.md
  • docs/TUI_INTERFACE.md
  • docs/MESSAGE_FLOW_AND_PROTOCOL.md

@arkanoider arkanoider merged commit 25ab002 into main May 24, 2026
11 checks passed
@arkanoider arkanoider deleted the feat/bond-enabled-add-bond-invoice branch May 24, 2026 16:30
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.

1 participant