Repository navigation
fix(swap-service): drop the block time tolerance and gate payouts on attribution - #65
Conversation
The window was sized on the reasoning that it cost nothing, which was wrong: it is exactly how long a second quote has to bind cleanly to a transaction someone already claimed. No row ever used it - all 28 accepted swaps in production read quote-precedes-tx - because backfilled rows carry their own headroom and a real quote precedes its broadcast. A rejection close enough to be miner clock skew is logged instead, so the case that motivated the tolerance is visible if it ever happens. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P36At9muenEn9Uqzjo1rDw
The payout script consulted verification but never attribution, so a rejected or contested claim was payable as long as its fee verified. Attribution now gates ahead of verification and unaccepted swaps join the review items, which is where an operator already looks before paying. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P36At9muenEn9Uqzjo1rDw
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (7)
💤 Files with no reviewable changes (1)
Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review. 📝 WalkthroughWalkthroughThe swap service now rejects quotes that postdate transaction blocks. The affiliate payout pipeline separates non-accepted attribution into an unattributed category, warnings, totals, summaries, and tests. ChangesQuote binding validation
Affiliate attribution handling
Priority: ⬇️ Low Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to Post-block quotes are rejected, and unsettled affiliate attributions are withheld from payouts while remaining visible for review. No concrete current-head merge-blocking risk remains. Sequence Diagram(s)sequenceDiagram
participant SwapRows
participant aggregateByPartner
participant buildRecord
participant PayoutSummary
SwapRows->>aggregateByPartner: rows with attribution status
aggregateByPartner->>buildRecord: unattributed swaps
buildRecord->>PayoutSummary: unattributedSwaps total
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 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. A rabbit checks each quoted time, Comment |
The payout run already lists every unaccepted swap with its status and reason, and the overshoot is derivable from attributionDetails, so the warning restated in logs what the review items say where it matters. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01P36At9muenEn9Uqzjo1rDw
Description
Two related changes to how a swap's quote binding is decided, and to whether anything consumes it.
Drop
BLOCK_TIME_TOLERANCE_MS. The tolerance extended the accept window past a transaction's block timestamp. It was sized on the reasoning that it cost nothing, but the boundary it moves is the only thing separating a quote that preceded its transaction from one that did not, so widening it is not free. It has also never been used: all 28 accepted swaps in production readquote-precedes-txand none readquote-within-tolerance, because backfilled rows carry their own headroom and a real quote precedes its own broadcast. The block timestamp is now the whole boundary.The case the tolerance was meant to cover — a miner-declared block timestamp lagging the broadcast it carries — remains observable without it. Every rejection records
blockTimeandquotedAtinattributionDetails, so the overshoot is queryable, and the payout run lists each unaccepted swap with its reason. If real rows ever cluster near zero, the constant can be reintroduced sized from that evidence rather than from assumption.Gate payouts on attribution.
scripts/affiliate-payoutsconsultedverificationStatusbut neverattributionStatus, so a swap whose binding had been rejected was still payable as long as its fee verified — the verdicts were written but nothing acted on them. Attribution now gates ahead of verification, since whether a claim is a partner's to be paid precedes whether its fee checked out. Unaccepted swaps join the existing review items with their status and reason, surfacing per-swap rather than as a bare count.The gate requires
ACCEPTEDrather than excludingREJECTED, so it fails closed —PENDINGandDISPUTEDare withheld too. Withholding is reversible; paying is not. One consequence worth knowing: a newly created swap is unpayable until the attribution pass reaches it, so a payout run overlapping that window lists those rows asunattributedrather than paying them.No query changes were needed;
findManyalready returned these columns unused.Testing
apps/swap-service: 98 tests pass. Tolerance cases were replaced with the boundary itself — a quote one second past its block now rejects.scripts/affiliate-payouts: 26 tests pass, including a new case assertingREJECTED,PENDINGandDISPUTEDare all withheld with their reasons carried into the review items.🤖 Generated with Claude Code
https://claude.ai/code/session_01P36At9muenEn9Uqzjo1rDw