Repository navigation
fix(swap-service): value fees paid in a third asset and report only what the payout pays - #78
Conversation
…n-chain fees - Look up fee asset precision in the web app's hosted asset list (cached, reloaded when its manifest hash changes) so a fee in neither swap asset, such as Relay's USDC on Base, gets its on-chain value - Affiliate stats and swaps report feeUsd and partnerFeeUsd from the on-chain fee only, null when it can't be valued, instead of the bps-implied estimate - The payout script fails if the asset list can't load rather than leaving those fees unpaid; referral fees use the lookup and keep their fallback Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…stats and swaps - Share the payout's per-swap rules (attribution accepted, verified, an on-chain fee within the deviation guard, a partner share configured) so the affiliate endpoints and the payout script can't drift apart - Affiliate stats totals and the fee fields on affiliate swaps count only payable swaps; everything else reports no fee - The payout script's report buckets are unchanged Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t anomalies from the shared rules - Serve the cached asset list while a due refresh runs; only the first load is waited on, and only the refresh logs a failure - resolvePartnerFee returns the fee deviation it held a swap back on, and the payout report describes that anomaly instead of recomputing it, so an excluded swap can't drop out of every report bucket - A non-finite deviation counts as an anomaly rather than passing the guard - Affiliate stats narrow the query to rows that can be payable - Tests for the shared payout rules and the asset list refresh Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
No actionable comments were generated in the recent review.
|
| Layer / File(s) | Summary |
|---|---|
Asset precision loading and fee calculation apps/swap-service/src/utils/assets.ts, apps/swap-service/src/utils/__tests__/assets.test.ts, apps/swap-service/src/swaps/utils.ts, apps/swap-service/src/swaps/__tests__/utils.test.ts |
The swap service loads and caches asset precisions. Fee calculation uses those precisions to value fees paid in assets outside the swap pair and known assets. Tests cover loading, refresh behavior, and fee valuation. |
Shared partner-fee resolution apps/swap-service/src/swaps/partner-fee.ts, apps/swap-service/src/swaps/__tests__/partner-fee.test.ts |
The resolver checks attribution, verification, affiliate status, fee availability, fee deviation, and positive partner basis points. Tests cover payable, excluded, and anomalous fee outcomes. |
Affiliate statistics and swap fee fields apps/swap-service/src/affiliate/affiliate.service.ts, apps/swap-service/src/affiliate/__tests__/affiliate.service.test.ts |
Statistics queries require successful verification, accepted attribution, and positive partner basis points. Statistics count only payable swaps and use actual fees for earned amounts. Swap fee fields are null for non-payable outcomes; volume can still use the calculated fee. |
Affiliate payout aggregation scripts/affiliate-payouts/affiliate-payouts.ts, scripts/affiliate-payouts/types.ts, scripts/affiliate-payouts/utils.ts, scripts/affiliate-payouts/affiliate-payouts.test.ts |
Payout aggregation supplies asset precisions to fee calculation and maps resolver exclusions to existing report buckets. Fee anomaly descriptions include deviation details or a reason when deviation cannot be validated. |
Priority:
Estimated code review effort: 3 (Moderate) | ~25 minutes
Change: Bug fix
Sequence Diagram(s)
sequenceDiagram
participant PayoutScript as affiliate-payouts.ts
participant AssetPrecisions as getAssetPrecisions
participant Aggregation as aggregateByPartner
participant FeeCalculator as calculateFeeForSwap
participant FeeResolver as resolvePartnerFee
PayoutScript->>AssetPrecisions: Load asset precision map
PayoutScript->>Aggregation: Start aggregation with precision-aware fee callback
Aggregation->>FeeCalculator: Calculate swap fee using precision map
Aggregation->>FeeResolver: Resolve fee eligibility
FeeResolver-->>Aggregation: Return payable or excluded outcome
Aggregation-->>PayoutScript: Return payout aggregation
Possibly related PRs
- shapeshift/microservices#77: Both PRs change affiliate payout reporting for verification, attribution, and swap outcomes.
Merge Risk: 
Minimal · up to 31244
-
No merge-blocking issue was established. Affiliate statistics and monthly payouts use different date-boundary conventions, so comparisons should use matching intervals.
Pre-merge checks: 
5
-
Full details: Title check
-
Explanation
The title names the two main changes: valuing partner fees paid in a third asset, and reporting only what the payout pays. The changeset adds precision lookup for assets outside the swap's two assets (assets.ts, utils.ts) and moves payout eligibility into a shared resolvePartnerFee module, which matches the 'report only what the payout pays' part. The title is specific and uses the conventional commit format. It is slightly long at 88 characters, but this does not reduce its relevance.
Full details: Docstring Coverage
-
Explanation
Docstring coverage is 80.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 5 functions across 12 files.
-
Finishing Touches
-
📝 Generate docstrings
-
- Commit to this branch
- Create a new PR
🧪 Generate unit tests (beta)
-
- Commit to this branch
- Create a new PR
-
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
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.
I’m a rabbit with a ledger, and the fee figures align.
I hop through cached precisions to check each token’s sign.
Accepted swaps may pass the gate; excluded ones are shown.
A deviation gets a reason when its value can’t be known.
I tuck the payout report away, then nibble clover green.
Comment @coderabbitai help to get the list of available commands.
Description
A partner fee collected in neither swap asset (Relay routes some fees to USDC on Base, for example) had no known precision, so its on-chain value was never computed. The payout report listed those swaps as "no verified on-chain fee" and left them unpaid, while the affiliate endpoints fell back to the bps-implied estimate for them. On October's data this left 19 partner swaps unpaid.
Fee asset precision
generatedAssetData.json). An asset's precision never changes, so nothing is stored: no migration, no backfill, no API change.One set of payout rules
swaps/partner-fee.ts, shared by the payout script and the affiliate endpoints./v1/affiliate/statstotals and thefeeUsd/partnerFeeUsdon/v1/affiliate/swapsnow count only swaps the payout would pay. Anything else reports no fee, never the bps-implied estimate, so the affiliate dashboard total, the revenue dashboard and the payout agree.Consumers of
/v1/affiliate/swaps: the revenue dashboard keys offpartnerFeeUsdand needs no change. A follow-up inwebswitches the affiliate dashboard topartnerFeeUsdand should deploy after this.Testing
yarn lintandyarn build(7/7) pass; swap-service tests (182) and affiliate payout tests (33) pass/v1/affiliate/statstotals for a partner against the payout report for the same monthSummary by CodeRabbit