Skip to content

Fix/cancelall pending only#848

Merged
grunch merged 2 commits into
lnp2pBot:mainfrom
Matobi98:fix/cancelall-pending-only
Jun 30, 2026
Merged

Fix/cancelall pending only#848
grunch merged 2 commits into
lnp2pBot:mainfrom
Matobi98:fix/cancelall-pending-only

Conversation

@Matobi98

@Matobi98 Matobi98 commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the bug where a buyer running /cancelall could cancel a sell order that was still waiting for the seller to pay the hold invoice (WAITING_PAYMENT), trapping the seller's funds in LND.

/cancelall now only cancels PENDING orders (published orders nobody has taken yet). Orders that are already being taken (WAITING_PAYMENT / WAITING_BUYER_INVOICE) are simply ignored — the command always runs and never blocks on them. Those orders must be handled individually with /cancel or through a dispute.

Closes #829

Problem

The /cancelall handler collected orders in three states (PENDING, WAITING_BUYER_INVOICE, WAITING_PAYMENT) and tried to cancel all of them, with special-case hold invoice logic inside the loop. The case sell + WAITING_PAYMENT was not handled, so the order fell through to the generic CANCELED block:

  • The hold invoice was not canceled on LND
  • The seller received no notification

If the seller then paid the invoice, subscribeToInvoice found the order already CANCELED and did nothing, leaving the funds permanently trapped:

error: Order status is not WAITING_PAYMENT on subscribeToInvoice. Actual status: CANCELED

Changes

  • bot/start.ts/cancelall now only fetches and cancels PENDING orders. Removed the per-order hold invoice logic from the loop (no longer needed, since pending orders have no locked funds). In-progress orders are left untouched and do not block the command.

Summary by CodeRabbit

  • Bug Fixes
    • Updated the “cancel all” action to only affect pending orders.
    • Prevented cancellation flows from applying to orders in other waiting states, reducing unintended invoice-related actions.
    • Kept the same behavior when no pending orders are found.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@Matobi98, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 31 minutes and 44 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 355bd94f-d340-4ee2-b9d8-d4576b5e4133

📥 Commits

Reviewing files that changed from the base of the PR and between b7b6eaa and a996f1b.

📒 Files selected for processing (1)
  • bot/start.ts

Walkthrough

/cancelall now queries only PENDING orders, keeps the existing no-orders response, and iterates that filtered set. The prior WAITING_BUYER_INVOICE and WAITING_PAYMENT aggregation and invoice-cancellation branches are removed.

Changes

Cancel-all order scope

Layer / File(s) Summary
/cancelall pending-only fetch
bot/start.ts
/cancelall now loads only PENDING orders and keeps the existing empty-result handling and per-order cancellation loop; the previous invoice-state aggregation and invoice-cancellation branches are removed.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~5 minutes

Possibly related issues

Possibly related PRs

  • lnp2pBot/bot#657: Both changes touch the cancellation flow for WAITING_PAYMENT orders, though this PR narrows /cancelall while that PR adds authorization checks in cancelOrder.

Suggested reviewers

  • Luquitasjeffrey
  • mostronatorcoder
  • grunch

Poem

A rabbit hopped to the cancelall gate,
Sniffed only PENDING, chose not to wait.
No invoice trails, no tangled thread,
Just tidy hops in the order bed.
🐰✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly reflects the main change: /cancelall now only targets pending orders.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@Matobi98 Matobi98 force-pushed the fix/cancelall-pending-only branch from b13b91b to b7b6eaa Compare June 26, 2026 18:43

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (1)
tests/bot/pending-payments.spec.ts (1)

1-2: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Move this job spec under the mirrored tests/jobs/ layout.

This tests jobs/pending_payments.ts, but it is placed in tests/bot/. As per coding guidelines, “Write Mocha + Chai specs in tests/** with .spec.ts suffix, mirroring source layout.”

🤖 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 `@tests/bot/pending-payments.spec.ts` around lines 1 - 2, The pending payments
spec is in the wrong test area and should mirror the source layout for jobs.
Move the `pending-payments.spec.ts` test that covers `attemptPendingPayments`
from `tests/bot/` into the matching `tests/jobs/` structure, keeping the same
`.spec.ts` naming so it aligns with `jobs/pending_payments.ts` and the repo’s
mirrored test layout convention.

Source: Coding guidelines

🤖 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 `@bot/scenes.ts`:
- Around line 181-200: The fallback in `bot/scenes.ts` inside the
confirmed-order branch is incorrectly persisting `order.status = 'SUCCESS'` when
`originalStatus.payment` or `sellerUser` is missing, bypassing the full success
flow in `completeOrderAsSuccess`. Change this path to fail closed: do not save
SUCCESS here, and instead log/alert the missing data and return early so only
the shared success routine handles confirmed orders with all required inputs.

In `@bot/start.ts`:
- Around line 505-509: The /cancelall flow in bot/start.ts is treating a failed
ordersActions.getOrders(ctx.user, 'PENDING') call as an empty result by
collapsing undefined into an empty array. Update the /cancelall logic to
distinguish a real no-orders case from a fetch failure: either let getOrders
propagate the error or handle the error path separately before deciding there
are no pending orders. Use the getOrders method in bot/ordersActions.ts and the
/cancelall handler in start.ts as the key points to adjust.

In `@jobs/pending_payments.ts`:
- Around line 40-67: The confirmed-without-payment path in the pending payments
flow is being treated inconsistently and can be retried as if it were still
pending. In the order-processing branches of pending_payments.ts (including the
logic around original/community status handling and completeOrderAsSuccess),
check is_confirmed first and treat missing payment details as terminal: log an
error/admin alert, mark the order as non-retryable, and do not fall through into
the payment retry path or save a partial success state. Ensure the same behavior
is applied across the original, current, and community branches so confirmed
orders without payment do not get reprocessed.

In `@ln/pay_request.ts`:
- Around line 126-130: The current payToBuyer flow treats both pending and
confirmed invoices as an early return, which skips the normal success handling
for confirmed payments. Update the status check around isPendingOrConfirmed so
only is_pending exits early; when the invoice is is_confirmed, continue through
the same success path that marks the order SUCCESS, sets routing_fee, updates
reputation, and notifies the buyer. Use the existing payToBuyer success logic
and LND payment details, and if those details are unavailable for a confirmed
invoice, fail closed and raise an alert instead of returning silently.

In `@util/completeOrder.ts`:
- Around line 28-31: The success update in completeOrder should only apply to
orders in eligible payment-flow states, not any non-SUCCESS status. Update the
Order.findOneAndUpdate predicate to use an explicit allowed-state check for the
transition handled by completeOrder, so terminal states like CANCELED or
disputed cannot be flipped back to SUCCESS. Keep the change scoped to the status
filter around order._id and the status transition logic.
- Around line 40-43: The trade counter updates in completeOrder are currently
done by mutating buyerUser and sellerUser and saving the documents, which can
lose concurrent increments. Update the logic in completeOrder to use atomic $inc
operations for trades_completed on both user records, then refresh or adjust the
in-memory buyerUser and sellerUser objects if later code in the flow relies on
the updated counts.

---

Nitpick comments:
In `@tests/bot/pending-payments.spec.ts`:
- Around line 1-2: The pending payments spec is in the wrong test area and
should mirror the source layout for jobs. Move the `pending-payments.spec.ts`
test that covers `attemptPendingPayments` from `tests/bot/` into the matching
`tests/jobs/` structure, keeping the same `.spec.ts` naming so it aligns with
`jobs/pending_payments.ts` and the repo’s mirrored test layout convention.
🪄 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: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 111ff79d-f6dc-4342-b1e1-d37d1cbc780c

📥 Commits

Reviewing files that changed from the base of the PR and between bf32684 and b13b91b.

📒 Files selected for processing (9)
  • bot/modules/community/scenes.ts
  • bot/scenes.ts
  • bot/start.ts
  • jobs/pending_payments.ts
  • ln/index.ts
  • ln/pay_request.ts
  • tests/bot/pending-payments.spec.ts
  • tests/ln/get-payment-status.spec.ts
  • util/completeOrder.ts

Comment thread bot/scenes.ts Outdated
Comment thread bot/start.ts Outdated
Comment thread jobs/pending_payments.ts Outdated
Comment thread ln/pay_request.ts Outdated
Comment thread util/completeOrder.ts Outdated
Comment thread util/completeOrder.ts Outdated
@Matobi98 Matobi98 marked this pull request as draft June 26, 2026 18:48
@Matobi98 Matobi98 marked this pull request as ready for review June 26, 2026 19:06

@Luquitasjeffrey Luquitasjeffrey left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

tACK, i think this is the intended behavior of the /cancelall command, the 'cancelall_success' message shows to the user "You have cancelled all your published orders!" which from my understanding means that it cancels all untaken orders.

@grunch grunch left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review — approve ✅

Strict review of the /cancelall change. The fix is correct, minimal, and a net improvement.

What it does

Previously /cancelall collected PENDING, WAITING_BUYER_INVOICE and WAITING_PAYMENT orders and ran per-order hold-invoice logic inside the loop. The sell + WAITING_PAYMENT case had no branch, so it fell through to the generic CANCELED block: the order was marked CANCELED in the DB but the hold invoice was never canceled on LND and the seller wasn't notified. If the seller then paid, subscribeToInvoice saw the order already CANCELED and the funds were trapped (#829). The PR scopes /cancelall to PENDING orders only.

Strengths (verified)

  • Fixes the trapped-funds bug correctly. PENDING orders have no locked funds, so status = CANCELED + save + deleteOrderFromChannel is the complete, safe operation. In-progress orders are left to /cancel / dispute flows, which already handle hold-invoice cancellation, cooperative cancel and notifications (bot/commands.ts).
  • Also fixes a latent second bug. The old loop used return inside the for (e.g. sell+WAITING_BUYER_INVOICEreturn cancelAddInvoice(...)), which aborted the entire /cancelall after the first in-progress order, silently leaving the user's other pending orders uncanceled. That's gone now.
  • Good error discrimination. getOrders returns undefined only when the query throws. The new if (orders === undefined) return; avoids the previous || [] collapse that would show "you have no orders" on a DB failure and silently abandon real pending orders.
  • No dead imports left behind — cancelAddInvoice, cancelShowHoldInvoice, cancelHoldInvoice are all still used elsewhere in start.ts. No type errors introduced.

Non-blocking suggestions

  • UX: successCancelAllOrdersMessage is sent unconditionally. A user who still has WAITING_PAYMENT / WAITING_BUYER_INVOICE orders gets a blanket "all orders canceled" message with no hint those were intentionally skipped. Consider telling the user that in-progress orders were left untouched and must be handled with /cancel.
  • Error feedback: if (orders === undefined) return; returns with no user-facing message on a DB error (only logged). Acceptable, but a short error reply would be friendlier.
  • Tests: Consider a regression test asserting /cancelall leaves a sell + WAITING_PAYMENT order untouched and cancels only PENDING orders, to lock in the fix.
  • Housekeeping: the branch is a few commits behind main; rebase before merge.

None of these block merging.

@grunch grunch merged commit fea5d84 into lnp2pBot:main Jun 30, 2026
5 checks passed
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.

Bug: /cancelall cancels orders that are already being taken (WAITING_PAYMENT / WAITING_BUYER_INVOICE)

3 participants