Skip to content

feat: persist buyer payout payment hash and preimage on the order#870

Open
grunch wants to merge 1 commit into
mainfrom
feat/869-persist-payout-proof
Open

feat: persist buyer payout payment hash and preimage on the order#870
grunch wants to merge 1 commit into
mainfrom
feat/869-persist-payout-proof

Conversation

@grunch

@grunch grunch commented Jul 7, 2026

Copy link
Copy Markdown
Member

Closes #869.

What

An order recorded the hold invoice hash/secret (order.hash, order.secret) but nothing about the outgoing payment to the buyer. The payout's payment hash and its preimage (proof of payment) were available on the payment result (payment.id, payment.secret) but discarded — only the routing fee was kept.

  • Add payout_hash and payout_preimage to the Order model (models/order.ts).
  • Set them from payment.id / payment.secret in both buyer-payout success paths: payToBuyer (ln/pay_request.ts) and attemptPendingPayments (jobs/pending_payments.ts).

Why

Scoped to buyer payouts (which have an order). Community earnings withdrawals have no order and already store their payout hash on the pending payment.

Scope note

Records the values going forward; orders completed before this change keep empty payout_hash/payout_preimage, so consumers should keep deriving the hash from buyer_invoice for the historical backlog. The two are complementary.

Tests

Adds tests/ln/payout_proof.spec.ts asserting a successful payToBuyer sets payout_hash, payout_preimage and routing_fee. npx tsc compiles cleanly; Prettier and ESLint report no issues.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X5uNqd26cC88p5HVqErRDU


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Successful payouts now save additional proof details on the order, making completed payment records easier to verify later.
    • Order records now keep both the payout hash and payout preimage alongside the existing success status and routing fee.
  • Tests
    • Added regression coverage to confirm payout proof is stored correctly after a successful buyer payout.

An order recorded the hold invoice hash/secret but nothing about the
outgoing payment to the buyer. The payout's payment hash and preimage
(proof of payment) were available on the payment result but discarded,
leaving that proof only on the node.

Add payout_hash and payout_preimage to the Order model and set them from
payment.id / payment.secret in both buyer-payout success paths (payToBuyer
and attemptPendingPayments). This makes the order a self-contained,
verifiable record of the payment and lets reconciliation read the outbound
hash directly instead of re-deriving it from buyer_invoice.

Adds a regression spec for the payToBuyer success path.

Closes #869.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X5uNqd26cC88p5HVqErRDU
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Adds payout_hash and payout_preimage fields to the order model, and persists these payment proof values (payment id and secret) onto the order in the pending payments job and the pay_request confirmation flow. Includes a new regression test verifying this behavior.

Changes

Payout proof persistence

Layer / File(s) Summary
Order model payout proof fields
models/order.ts
IOrder interface and orderSchema gain optional payout_hash and payout_preimage string fields.
Persist payout proof in pending payments job
jobs/pending_payments.ts
On confirmed payment, saves payment.id and payment.secret onto order.payout_hash and order.payout_preimage.
Persist payout proof in pay_request flow
ln/pay_request.ts
Records payment hash and preimage onto the order before order.save() in the buyer payout confirmation path.
Regression test for payout proof
tests/ln/payout_proof.spec.ts
New test suite stubs payToBuyer dependencies and asserts payout_hash, payout_preimage, routing_fee, and order status are correctly set and saved.

Estimated code review effort: 2 (Simple) | ~10 minutes

Suggested reviewers: Luquitasjeffrey, mostronatorcoder

Poem

A hop, a skip, a payment sent,
Hash and preimage safely kept,
No more secrets lost in flight,
Order fields now shining bright,
This bunny saves proof with a happy leap! 🐇🔐

🚥 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 clearly summarizes the main change: persisting buyer payout hash and preimage on the order.
Linked Issues check ✅ Passed The PR adds payout_hash and payout_preimage and sets them in both buyer-payout success paths as requested in #869.
Out of Scope Changes check ✅ Passed The code changes and test stay focused on buyer payout proof persistence and do not introduce unrelated scope.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ 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/869-persist-payout-proof

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.

@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.

🧹 Nitpick comments (2)
jobs/pending_payments.ts (1)

86-93: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Test coverage gap: only payToBuyer has a regression test.

The new payout_hash/payout_preimage assignment here mirrors ln/pay_request.ts, but tests/ln/payout_proof.spec.ts only exercises payToBuyer. This confirmed-payment branch of attemptPendingPayments is untested for the new fields.

Want me to draft a proxyquire-based spec for attemptPendingPayments mirroring the existing payout_proof.spec.ts structure?

🤖 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 `@jobs/pending_payments.ts` around lines 86 - 93, The confirmed-payment branch
in attemptPendingPayments is missing regression coverage for the new payout_hash
and payout_preimage assignments. Add a spec alongside the existing payout_proof
coverage that exercises attemptPendingPayments with a confirmed payment and
asserts the order gets the hash/preimage copied over, using the same
proxyquire-based setup as payout_proof.spec.ts and referencing
attemptPendingPayments, payment.confirmed_at, and the order fields.
models/order.ts (1)

15-16: 🗄️ Data Integrity & Integration | 🔵 Trivial | 💤 Low value

Consider a partial unique index for payout_hash.

hash and secret both have unique indexes (with partialFilterExpression to allow nulls) to guard against duplicate outgoing/incoming payment records. payout_hash/payout_preimage get no such constraint, so a bug that pays two orders with the same payment (or double-writes) wouldn't be caught at the DB layer.

♻️ Optional index suggestion
-  payout_hash: { type: String }, // payment hash of the outgoing payment to the buyer
+  payout_hash: {
+    type: String,
+    index: {
+      unique: true,
+      partialFilterExpression: { payout_hash: { $type: 'string' } },
+    },
+  }, // payment hash of the outgoing payment to the buyer
   payout_preimage: { type: String }, // preimage (proof of payment) of the buyer payout

Also applies to: 89-90

🤖 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 `@models/order.ts` around lines 15 - 16, Add a partial unique index for
payout_hash, similar to the existing hash/secret uniqueness guards, so duplicate
payout records are caught at the DB layer while still allowing null values.
Update the Order model/index definition where payout_hash and payout_preimage
are declared, and make sure the new index uses a partialFilterExpression like
the other unique payment indexes.
🤖 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.

Nitpick comments:
In `@jobs/pending_payments.ts`:
- Around line 86-93: The confirmed-payment branch in attemptPendingPayments is
missing regression coverage for the new payout_hash and payout_preimage
assignments. Add a spec alongside the existing payout_proof coverage that
exercises attemptPendingPayments with a confirmed payment and asserts the order
gets the hash/preimage copied over, using the same proxyquire-based setup as
payout_proof.spec.ts and referencing attemptPendingPayments,
payment.confirmed_at, and the order fields.

In `@models/order.ts`:
- Around line 15-16: Add a partial unique index for payout_hash, similar to the
existing hash/secret uniqueness guards, so duplicate payout records are caught
at the DB layer while still allowing null values. Update the Order model/index
definition where payout_hash and payout_preimage are declared, and make sure the
new index uses a partialFilterExpression like the other unique payment indexes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 97b3f933-2fc9-49ae-8a30-b2b1cc713c75

📥 Commits

Reviewing files that changed from the base of the PR and between e45b8ec and 6fa082b.

📒 Files selected for processing (4)
  • jobs/pending_payments.ts
  • ln/pay_request.ts
  • models/order.ts
  • tests/ln/payout_proof.spec.ts

@grunch
grunch requested a review from Luquitasjeffrey July 7, 2026 18:28
@grunch

grunch commented Jul 7, 2026

Copy link
Copy Markdown
Member Author

@codex review

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.

Persist the buyer payout's payment hash and preimage on the order

2 participants