feat(add-bond-invoice): implement AddBondInvoice action#169
Conversation
Bump mostro-core 0.11.1 -> 0.11.3, which adds Action::AddBondInvoice and the Payload::BondPayoutRequest variant, and implement both directions of the bond payout invoice flow in the CLI: - Outbound (counterparty -> Mostro): new `addbondinvoice -o <id> -i <inv>` command that replies to a slash with a bolt11 for the counterparty's share, signed with the order's trade key (Payload::PaymentRequest). A timeout while waiting is treated as success since Mostro pays without acknowledging; only `cant-do` is surfaced on failure. - Inbound (Mostro -> counterparty): render the BondPayoutRequest in both print_commands_results and getdm, computing the forfeit deadline locally from the on-wire `slashed_at` (never local clock) plus the node's `bond_payout_claim_window_days` info-event tag. - Add fetch_bond_claim_window_days helper to read the kind-38385 info event tag, queried lazily from getdm only when a request is present. Update README command reference and add a parser test for the request rendering across known/unknown claim windows. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
WalkthroughAdds an ChangesBond Invoice Submission and Display
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a29e90f1a5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
src/cli/add_bond_invoice.rs (1)
53-75: 💤 Low valueUnwrap the redundant
Optionaroundpayload.
payloadis typed asOption<Payload>but is alwaysSome(...)once the else branch returnsErr. Constructing the value directly is clearer and matches the actual contract.♻️ Proposed simplification
- // Parse invoice (Lightning address or BOLT11) and build payload - let ln_addr = LightningAddress::from_str(invoice); - let payload = if ln_addr.is_ok() { - Some(Payload::PaymentRequest(None, invoice.to_string(), None)) - } else { - match is_valid_invoice(invoice) { - Ok(i) => Some(Payload::PaymentRequest(None, i.to_string(), None)), - Err(e) => { - return Err(anyhow::anyhow!("Invalid invoice: {}", e)); - } - } - }; + // Parse invoice (Lightning address or BOLT11) and build payload + let payment_request = if LightningAddress::from_str(invoice).is_ok() { + invoice.to_string() + } else { + is_valid_invoice(invoice) + .map(|i| i.to_string()) + .map_err(|e| anyhow::anyhow!("Invalid invoice: {}", e))? + }; + let payload = Some(Payload::PaymentRequest(None, payment_request, None));🤖 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/cli/add_bond_invoice.rs` around lines 53 - 75, The payload variable is wrapped in an unnecessary Option even though errors return early; change payload to be a Payload (not Option<Payload>) by assigning either Payload::PaymentRequest(...) from the LightningAddress::from_str branch or from the is_valid_invoice match branch, and then pass Some(payload) into Message::new_order; update references to payload, Payload::PaymentRequest, LightningAddress::from_str, is_valid_invoice, Message::new_order, and Action::AddBondInvoice accordingly.
🤖 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/cli/add_bond_invoice.rs`:
- Around line 93-106: The match in add_bond_invoice treats any Err from
wait_for_dm(...) as a successful submission; change it to detect the
timeout-specific error from wait_for_dm and only print the “✅ Bond payout
invoice submitted…” messages in that timeout/happy-path case, while propagating
or logging any other Err values (originating from ctx.client.subscribe,
sent_message.await, etc.) back to the caller or as an actual failure. Update
wait_for_dm to return a typed error or ensure it maps timeout to a
distinguishable variant, then match on that variant in add_bond_invoice (keeping
print_dm_events(...) on Ok) and handle non-timeout errors by returning Err or
printing an error message so send/sign/transport failures aren’t misreported as
success.
---
Nitpick comments:
In `@src/cli/add_bond_invoice.rs`:
- Around line 53-75: The payload variable is wrapped in an unnecessary Option
even though errors return early; change payload to be a Payload (not
Option<Payload>) by assigning either Payload::PaymentRequest(...) from the
LightningAddress::from_str branch or from the is_valid_invoice match branch, and
then pass Some(payload) into Message::new_order; update references to payload,
Payload::PaymentRequest, LightningAddress::from_str, is_valid_invoice,
Message::new_order, and Action::AddBondInvoice accordingly.
🪄 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: 1573ea97-d3c1-460c-a67f-49c07040c916
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (9)
Cargo.tomlREADME.mdsrc/cli.rssrc/cli/add_bond_invoice.rssrc/cli/get_dm.rssrc/parser/dms.rssrc/util/events.rssrc/util/mod.rstests/parser_dms.rs
…sion Previously any error from wait_for_dm was reported as "invoice submitted", so a subscribe/sign/transport failure where the reply never went out was misreported as success. Introduce a distinguishable WaitForDmTimeout error and only show the success message on that timeout (the genuine no-reply happy path), propagating every other error. Also drop the unnecessary Option wrapper around the payload, which is always Some by the time it is used (invalid invoices return early). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Strict review on current head 5c047126fb7f6afd164fb2d237486742f85cf031.
One issue left before this is mergeable:
src/parser/dms.rs:148printsmostro-cli addbondinvoice --orderid ..., but the actual clap long flag generated fromorder_idis--order-id(or-o). Following the printed command literally will fail, so the user guidance for the new inboundAddBondInvoiceflow is wrong right now.
I ran:
cargo testcargo clippy --all-targets --all-features -- -D warnings
Both pass on this head, but the bad printed command is still a real UX bug in the new flow, so I'm requesting changes.
The inbound bond-payout hint printed the long flag `--orderid` (correct, since the Commands enum's `rename_all = "lower"` renames `order_id` to `--orderid`), but the unusual form is easy to misread. Switch the hint to the short `-o`/`-i` flags, which are unambiguous and match the README's convention for these commands. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Re: the The So the originally printed That said, since |
- fetch_bond_claim_window_days: select the kind-38385 info event by max created_at instead of relying on limit(1) + .first(), so a lagging or multi-relay setup can't surface a stale bond_payout_claim_window_days and render the wrong, user-facing forfeit deadline. - execute_add_bond_invoice: the protocol's bond-payout reply is a bolt11, so stop forwarding Lightning Addresses verbatim (they'd bounce back as cant-do/invalid-invoice from Mostro). Validate the bolt11 locally and fail fast with a clear error; drop the now-unused LightningAddress/FromStr imports. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Summary
Bumps
mostro-core0.11.1→0.11.3and implements theAddBondInvoiceaction (protocol: Bond payout invoice), the counterparty-direction dual ofpay-bond-invoice.mostro-core 0.11.1 → 0.11.3 changes adopted
0.11.2:Action::AddBondInvoice.0.11.3:Payload::BondPayoutRequest(BondPayoutRequest { order, slashed_at });get_payment_request()extended toAddBondInvoice;BondPayoutRequestexported from the prelude.CLI changes — both directions of the flow
addbondinvoice -o <id> -i <invoice>command that replies to a slash with a bolt11 for the counterparty's share, signed with the order's trade key (Payload::PaymentRequest). A wait timeout is treated as the happy path (Mostro pays from its wallet without acking); only acant-doresponse is surfaced as an error.BondPayoutRequestin bothprint_commands_resultsandgetdm, computing the forfeit deadline locally from the on-wireslashed_at(never the local clock) plus the node'sbond_payout_claim_window_days, per the protocol.fetch_bond_claim_window_dayshelper reads thebond_payout_claim_window_daystag from the kind-38385 info event, queried lazily fromgetdmonly when a bond payout request is actually present.Testing
cargo fmt --check,cargo clippy --all-targets --all-features -- -D warnings, andcargo testall pass.0.17.3, bonds enabled):fetch_bond_claim_window_daysreturnedSome(1)matching the node'sbond_payout_claim_window_daystag, and the deadline math is correct.🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
addbondinvoiceCLI command to submit invoices for bond payout requests.Chores