fix: guard weighted-average merge against zero outputAmountSum in historicalOrderCharts - #2777
fix: guard weighted-average merge against zero outputAmountSum in historicalOrderCharts#2777thedavidmeister wants to merge 14 commits into
Conversation
…toricalOrderCharts When two or more trades share a timestamp and their outputVaultBalanceChange.amount values sum to zero, dividing ioratioSum by outputAmountSum produced NaN/Infinity. Falls back to unweighted mean of ioratio values when outputAmountSum === 0. Closes #2766 Co-Authored-By: Claude <noreply@anthropic.com>
📝 WalkthroughWalkthrough
ChangesZero-output merge guard and test
Estimated code review effort: 2 (Simple) | ~8 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 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. Comment |
… helper
id parameter and orderHash literal in the inline test helper must satisfy
the `0x${string}` template literal type required by RaindexTrade.
Co-Authored-By: Claude <noreply@anthropic.com>
RaindexTrade is a WASM class with a private constructor and additional required fields (chainId, formattedIoRatio, ioRatio, owner). The inline test helper builds a partial object literal, so cast through unknown rather than enumerate all required properties. Co-Authored-By: Claude <noreply@anthropic.com>
Run prettier on historicalOrderCharts.ts.
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 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 `@packages/ui-components/src/lib/services/historicalOrderCharts.ts`:
- Around line 51-55: The fallback calculation for ioratioAverage when
outputAmountSum === 0 does not guard against d.value being non-finite (Infinity
or NaN), which can occur when outputVaultBalanceChange.formattedAmount is "0"
from the initialization at lines 22-25. Filter out non-finite values from the
fallback average calculation by adding a check to ensure each d.value is finite
before including it in the reduce operation. Additionally, update the test
fixture that currently hardcodes "100" to test with "0" values that would expose
this non-finite path and verify the fix handles it correctly.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 68d77525-228b-4304-b28e-e4ae2687eef8
📒 Files selected for processing (1)
packages/ui-components/src/lib/services/historicalOrderCharts.ts
When outputVaultBalanceChange.amount is BigInt(0) the formattedAmount is also "0", making the per-trade value Infinity/NaN. The previous fallback divided Infinity × N / N = Infinity. Filter non-finite values before the unweighted mean; if every entry is non-finite (i.e. all output amounts are zero), return 0. Update the test fixture to use formattedAmount:"0" (consistent with amount BigInt(0)) and tighten the assertion to expect value 0. Co-Authored-By: Claude <noreply@anthropic.com>
…-historical-chart-divide-zero
|
screenshot pending (manual): historicalOrderCharts.ts produces data for lightweight-charts canvas rendering — canvas output requires a headless Chromium harness to screenshot; the change itself is a computation fix (unweighted-mean fallback when outputAmountSum is 0) with no layout change |
…-historical-chart-divide-zero
|
🤖 ai:vetter |
|
Rework note (human): simplify so all branches are reachable + covered. The const ioratioAverage =
outputAmountSum === 0 ? 0 : ioratioSum / outputAmountSum;Delete the |
…-historical-chart-divide-zero
…e (rework) outputAmountSum === 0 implies every merged value is Infinity (division by the zero formatted amount), so the finite-values unweighted-mean branch could never execute; the bucket charts as zero directly. Co-Authored-By: Claude <noreply@anthropic.com>
|
🤖 ai:producer |
|
🤖 ai:producer |
|
🤖 ai:producer |
|
🤖 ai:producer |
|
🤖 ai:vetter |
…-historical-chart-divide-zero
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/ui-components/src/lib/services/historicalOrderCharts.ts (1)
474-552: 📐 Maintainability & Code Quality | 🔵 TrivialRun the UI-components lint/check suite before merge.
🤖 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 `@packages/ui-components/src/lib/services/historicalOrderCharts.ts` around lines 474 - 552, Run the UI-components lint and check suite for the updated historical order chart test and resolve any reported issues before merging, keeping the test behavior unchanged.Source: Coding guidelines
🤖 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 `@packages/ui-components/src/lib/services/historicalOrderCharts.ts`:
- Around line 51-53: Update the comment in the historical order chart
aggregation around outputAmountSum to state that a zero signed output sum can
result from non-zero output amounts canceling each other, and that the bucket is
charted as zero to avoid dividing by zero.
---
Nitpick comments:
In `@packages/ui-components/src/lib/services/historicalOrderCharts.ts`:
- Around line 474-552: Run the UI-components lint and check suite for the
updated historical order chart test and resolve any reported issues before
merging, keeping the test behavior unchanged.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 77374caf-9a45-4387-8d71-a09b609f56b6
📒 Files selected for processing (1)
packages/ui-components/src/lib/services/historicalOrderCharts.ts
|
🤖 ai:vetter |
|
🤖 ai:vetter |
|
🤖 ai:producer |
|
🤖 ai:producer |
|
🤖 ai:producer Producer note — body-claim correction at head d4e88d9. Two claims in this PR's FALSE — verbatim from the body:
WHAT THE DIFF ACTUALLY DOES:
The code is unchanged by this note — only the record is corrected. A truthful Correcting the false PROSE itself needs a human body edit: |
|
🤖 ai:producer |
|
👤 human |
|
Rework note @61ed3f2c9848e86e60ca7880834aad4512559377: The body edit you asked for is DONE — I applied it. Do not re-edit the body, and do not re-raise this. What I changed, and why it is not the staged file verbatim: the staged /home/gildlab/code/pr2777-body-corrected.md had three defects, not the one you flagged. (a) Its CodeRabbit section claimed coverage for "per-trade ratio inputs are non-finite", which no test in this diff asserts — you flagged that one. (b) It carried NO Remaining work, and your classification of it is wrong:
|

Summary
prepareHistoricalOrderChartDatawhen two or more trades share a timestamp and theiroutputVaultBalanceChange.amountvalues sum to zerooutputAmountSum === 0, charts the bucket value as0instead of dividing by zero (which would produceNaNor±Infinity)0Screenshot: posted as a comment on this PR — the real
LightweightChart.sveltemounted on realprepareHistoricalOrderChartData()output, merge-base formula on the left and this guard on the right.Closes #2766
Co-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit
Bug Fixes
0instead of error-prone results.Tests
0.QA
charts zero when same-timestamp outputAmounts sum to zero(the single test this PR adds; assertsresult.length === 1andresult[0].value === 0) — fails on base (restored the base source lineconst ioratioAverage = ioratioSum / outputAmountSum;under the new test and re-ran scoped vitest:AssertionError: expected NaN to deeply equal +0, 1 failed | 5 passed; unmutated baseline before and after is 6 passed | 6,vitest run src/lib/services/historicalOrderCharts.tsin packages/ui-components)historicalOrderCharts.ts:54-55guard deleted → plainioratioSum / outputAmountSum(the base line) → killed bycharts zero when same-timestamp outputAmounts sum to zero(NaN vs +0); same line zero-branch constant? 0→? 1→ killed by that same test (1 vs +0), so it pins the exact value 0 and not merely finiteness; same line non-zero branchioratioSum / outputAmountSum→ioratioSum / objectsWithSameTimestamp.length(unweighted mean) → killed by pre-existinghandles the case where multiple trades have the same timestamp(50 vs 0.21428571428571427); same line comparisonoutputAmountSum === 0→outputAmountSum <= 0→ SURVIVED, 6 passed | 6 — no merge-bucket test uses a negativeoutputAmountSum, which per historicalOrderCharts: weighted-average merge divides by zero (NaN/Infinity chart point) when same-timestamp trades' output amounts sum to zero #2766 is the production-typical sign, so the guard's boundary is unpinned on that side (the=== 0behaviour there is correct — weights of one sign cancel in the ratio, e.g. two -100 outputs at ratios 0.5/0.25 give -75 / -200 = 0.375 — so this is a test gap, not a code bug)NaN/±Infinityas a chart point — plus the human rework note on this PR, which chose charting0as the fallback and directed the ternary collapse; the value the new test asserts (0) comes from that ruling, not from running the implementation. Caveat on the other side: the pre-existing weighted-average test recomputes its expected value with the same formula the code uses, from the fixture literals ((0.5100 + 0.25200 + 0.125*400) / (100+200+400)), so it pins the weighted branch but does not independently validate it.outputAmountSum === 0before dividing so noNaN/±Infinityreaches the chart, and (b) a test covering >=2 same-timestamp trades whose output amounts sum to zero — covered a and b. The issue's other illustrative shape, non-zero same-timestamp amounts that cancel to a zero sum, is covered by the same=== 0guard but is not separately tested (the human rework note ruled it unreachable: same-order output balance changes at one timestamp share a sign); the surviving<= 0mutant above is the adjacent negative-sum region of that same boundary and is likewise untested.