Skip to content

fix(affiliate): exact partner-fee math via getPartnerFeeUsd across stats, swaps, and payouts - #51

Merged
kaladinlight merged 3 commits into
developfrom
fix/partner-fee-precision
Jul 2, 2026
Merged

fix(affiliate): exact partner-fee math via getPartnerFeeUsd across stats, swaps, and payouts#51
kaladinlight merged 3 commits into
developfrom
fix/partner-fee-precision

Conversation

@kaladinlight

Copy link
Copy Markdown
Member

Description

Consolidates the partner-fee-share calculation onto a single exact helper, getPartnerFeeUsd, and removes getPartnerFeeRate.

The old pattern feeUsd × getPartnerFeeRate(...) multiplies by a lossy float rate (e.g. 50/60 → 0.8333…4), which reintroduces binary-float artifacts (e.g. "0.050000000000000004"). getPartnerFeeUsd multiplies before dividing (feeUsd × partnerBps ÷ verifiedBps, capped at the fee), so the result is exact.

Applied across all three consumers:

  • getAffiliateSwaps — per-swap partnerFeeUsd (a full-precision string, so the artifact was directly visible in the response)
  • getAffiliateStats — aggregate totals accumulated in BigNumber, so they reconcile exactly with the sum of the per-swap rows
  • affiliate-payouts script (aggregateByPartner) — pays the partner share via the same helper; the partnerBpsUnset bucket now gates on partnerBps directly. Payout amounts are unchanged (they floor to 6 dp), so there it's precision-hygiene, not a value change.

With all three on getPartnerFeeUsd, getPartnerFeeRate has no remaining callers and is deleted.

Follow-up to #50 (partner revenue breakout) — the get-stats/get-swaps precision changes were split out of that PR so the fee-precision work reviews as one holistic unit.

Testing

  • yarn build — all 6 packages build
  • swap-service — affiliate tests pass (8/8)
  • yarn affiliate-payouts:test — 25/25 pass

🤖 Generated with Claude Code

kaladinlight and others added 3 commits July 2, 2026 17:36
…lper

feeUsd × getPartnerFeeRate multiplies by a lossy float rate (e.g. 50/60), which
can leave binary-float artifacts in the "full precision" string. Add a fee-aware
getPartnerFeeUsd helper that multiplies before dividing (feeUsd × partnerBps ÷
verifiedBps, capped at the fee) so the result is exact, and use it in
getAffiliateSwaps. getPartnerFeeRate is unchanged for its rate-based callers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
getAffiliateStats now accumulates volume/fees in BigNumber and derives the
partner fee via getPartnerFeeUsd, so the aggregate reconciles exactly with the
sum of the per-swap partnerFeeUsd rows (no float-accumulation drift). Displayed
2dp output is unchanged. Drops the now-unused getPartnerFeeRate import.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…artnerFeeRate

Migrate the affiliate-payouts script's aggregateByPartner to the exact
getPartnerFeeUsd helper (multiply-before-divide) rather than the lossy
actualFeeUsd × getPartnerFeeRate float, and gate the partnerBpsUnset bucket on
partnerBps directly. The affiliate service already uses getPartnerFeeUsd, so
getPartnerFeeRate now has no callers and is removed.

Payout amounts are unchanged (floored to 6dp); this just unifies the partner-fee
definition and removes the float-artifact source across all three consumers.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@kaladinlight, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 25 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

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

How do review 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 refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1d1bde1d-30ee-4736-86db-64e89c8151db

📥 Commits

Reviewing files that changed from the base of the PR and between f252430 and 4c6eb59.

📒 Files selected for processing (6)
  • apps/swap-service/src/affiliate/affiliate.service.ts
  • apps/swap-service/src/swaps/utils.ts
  • scripts/affiliate-payouts/affiliate-payouts.test.ts
  • scripts/affiliate-payouts/affiliate-payouts.ts
  • scripts/affiliate-payouts/types.ts
  • scripts/affiliate-payouts/utils.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/partner-fee-precision

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.

@kaladinlight
kaladinlight merged commit bdc8da0 into develop Jul 2, 2026
2 checks passed
@kaladinlight
kaladinlight deleted the fix/partner-fee-precision branch July 2, 2026 23:45
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.

1 participant