feat : Indexer Handler InvoicePaidEvent - #38
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (2)
🚧 Files skipped from review as they are similar to previous changes (2)
📝 WalkthroughWalkthroughThe indexer now registers and processes ChangesInvoice payment synchronization
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant Indexer
participant handleInvoicePaid
participant decodeInvoicePaidEventData
participant applyInvoicePayment
participant Prisma
Indexer->>handleInvoicePaid: dispatch InvoicePaid event
handleInvoicePaid->>decodeInvoicePaidEventData: decode payload
decodeInvoicePaidEventData-->>handleInvoicePaid: normalized event data
handleInvoicePaid->>applyInvoicePayment: pass event data and txHash
applyInvoicePayment->>Prisma: update invoice and create transaction
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 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.
Actionable comments posted: 1
🧹 Nitpick comments (2)
tests/unit/invoice.services.test.ts (1)
164-254: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winConsider covering the merchant-not-found and merchant-mismatch branches.
The new suite exercises partial payment, completed payment, and missing-invoice skip, but not the merchant-not-found or
invoice.merchantId !== merchant.idskip branches inapplyInvoicePayment.🤖 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/unit/invoice.services.test.ts` around lines 164 - 254, Extend the applyInvoicePayment tests to cover both merchant skip branches: when merchant.findUnique returns null and when the invoice merchantId differs from the fetched merchant id. Assert each case logs the expected warning, resolves without applying payment, and does not invoke transaction processing.src/indexer/types.ts (1)
39-62: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick winAdd non-negativity checks for monetary bigint fields; tighten
toStringtyping.
toBigInt/toSafeNumberenforce safe-integer bounds only forinvoiceId/merchantId/timestamp;amount,fee, andmerchantAmountare converted with plaintoBigIntand accept negative values. Soroban amounts are typicallyi128(signed), so nothing structurally prevents a negative value from reachingapplyInvoicePayment, where it's added directly toinvoice.amountPaidand could corrupt payment totals/status.Separately,
toStringcallsString(value)unconditionally — a non-string/non-null value (e.g. an object) would silently coerce to"[object Object]"instead of failing loudly, unlike the other coercion helpers.♻️ Suggested tightening
+const toNonNegativeBigInt = (value: unknown, field: string): bigint => { + const parsed = toBigInt(value, field); + if (parsed < 0n) { + throw new Error(`InvoicePaid event field "${field}" cannot be negative`); + } + return parsed; +}; + const toString = (value: unknown, field: string): string => { - if (value === null || value === undefined) { + if (typeof value !== 'string') { throw new Error(`InvoicePaid event field "${field}" is required`); } - return String(value); + return value; };Then use
toNonNegativeBigIntforamount,fee, andmerchantAmountindecodeInvoicePaidEventData.Please confirm whether the Soroban
InvoicePaidEventcontract enforces non-negative amounts on-chain (e.g. via anassert!), which would make this defensive check redundant but still cheap insurance against malformed/adversarial decoded payloads.🤖 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/indexer/types.ts` around lines 39 - 62, Update the monetary-field conversion in decodeInvoicePaidEventData to use a new toNonNegativeBigInt helper for amount, fee, and merchantAmount, rejecting values below zero before applyInvoicePayment receives them. Tighten toString to accept only string values (while retaining the existing required check), and throw for other types instead of coercing them with String(value).
🤖 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/services/invoice.services.ts`:
- Around line 190-251: Move the `amountPaid` and `status` calculation into the
`prisma.$transaction` callback in `applyInvoicePayment`, re-read the invoice
there using the transaction client, and derive both values from that fresh row
before `tx.invoice.update`. Use the transaction-scoped invoice amount and
identifier while preserving the existing payment and transaction creation
behavior.
---
Nitpick comments:
In `@src/indexer/types.ts`:
- Around line 39-62: Update the monetary-field conversion in
decodeInvoicePaidEventData to use a new toNonNegativeBigInt helper for amount,
fee, and merchantAmount, rejecting values below zero before applyInvoicePayment
receives them. Tighten toString to accept only string values (while retaining
the existing required check), and throw for other types instead of coercing them
with String(value).
In `@tests/unit/invoice.services.test.ts`:
- Around line 164-254: Extend the applyInvoicePayment tests to cover both
merchant skip branches: when merchant.findUnique returns null and when the
invoice merchantId differs from the fetched merchant id. Assert each case logs
the expected warning, resolves without applying payment, and does not invoke
transaction processing.
🪄 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: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: de4da130-5ade-4da8-beed-4e5fe7a4bada
📒 Files selected for processing (8)
src/controllers/pay.controllers.tssrc/indexer/handlers/index.tssrc/indexer/handlers/invoicePaid.tssrc/indexer/run.tssrc/indexer/types.tssrc/services/invoice.services.tstests/unit/invoice-paid.handler.test.tstests/unit/invoice.services.test.ts
|
Hello @ryzen-xp |
|
Hello @codebestia check again |
codebestia
left a comment
There was a problem hiding this comment.
LGTM!
Nice implementation.
Thank you for your contribution.
InvoicePaidEvent→ Invoice State Sync #30Summary
Implements Soroban
InvoicePaidevent handling to synchronize on-chain invoice payments into backend state.InvoicePaidhandler when the indexer starts.InvoicePaidEventData.applyInvoicePaymentto update invoices and createINVOICE_PAYMENTtransactions atomically.PARTIALLY_PAID) and completed payments (PAIDwithdatePaid).POST /pay/:slug/confirmbackward-compatible but explicitly non-authoritative; invoice state is now driven by on-chain events.Validation
npm test -- --runInBand— 32 suites, 251 tests passednpx tsc --noEmitnpm run format:checknpm run lint:check— no errors; existing warnings remainNotes
InvoicePaidis registered from the contract event definition and normalized using its actual payload fields (invoice_id,merchant_id,merchant_amount, etc.). Live testnet E2E verification still requires a configuredSTELLAR_CONTRACT_IDand matching database records.Summary by CodeRabbit
New Features
Bug Fixes
Tests