Skip to content

feat(frontend): add FIFO cost-basis tax report with CSV export (Closes #605) - #937

Open
waterWang wants to merge 1 commit into
FinChippay:mainfrom
waterWang:feat/portfolio-tax
Open

feat(frontend): add FIFO cost-basis tax report with CSV export (Closes #605)#937
waterWang wants to merge 1 commit into
FinChippay:mainfrom
waterWang:feat/portfolio-tax

Conversation

@waterWang

Copy link
Copy Markdown
Contributor

Summary

Adds a FIFO cost-basis tax report to the portfolio UI (issue #605):

  • lib/portfolio.ts — new computeFIFOTaxReport() FIFO engine: received events open acquisition lots priced at historical CoinGecko prices; sent events dispose against the oldest lot first and contribute realized gains/losses; remaining lots are valued at the latest event price for unrealized gains. Missing historical prices flag the position as unpriced instead of producing wrong numbers.
  • lib/portfolio.tsfetchHistoricalPrices() (CoinGecko market_chart) and historicalPriceLookup() (back-fill ~5 days for weekend/holiday gaps, live-price fallback).
  • components/TaxReport.tsx (new) — loads payment history + historical prices, renders a summary card (realized / unrealized / assets), a per-asset table (remaining qty, cost basis, unrealized, lots, priced flag), and a CSV export of the report.
  • pages/portfolio.tsx — Portfolio ⇄ Tax Report tab switcher.
  • i18nportfolio.tabOverview / portfolio.tabTaxReport / taxReport.* keys added to all 7 locale files.
  • Tests — 5 FIFO engine unit tests (single lot, realized gain on disposal, oldest-lot-first ordering, unpriced flag, order-independence + swap as paired events) and 3 TaxReport component tests (connect prompt, empty state, summary render).

Implementation notes

  • FIFO ordering is applied internally, so the feed direction doesn't matter.
  • Swap/trade operations are surfaced as paired sent(out) + received(in) events and are taxed naturally by the engine.
  • CoinGecko pricing only covers XLM/USDC (existing COINGECKO_ID_MAP); other assets are flagged as unpriced rather than guessed.
  • Non-XLM/USDC transaction values in CSV are reported in the raw event amounts; fiat columns are computed for priced assets.

Verification

  • NODE_ENV=test npx jest __tests__/portfolio.test.ts __tests__/TaxReport.test.tsx __tests__/PortfolioOverview.test.tsx __tests__/PortfolioAllocation.test.tsx39/39 pass.
  • tsc --noEmit — only pre-existing lib/sdk-instance.ts errors (TS1127/TS1160, introduced by PR#918 on main, unrelated to this change).
  • eslint clean on all changed files (pre-existing require() in portfolio.test.ts mock untouched).

Closes #605

Signed-off-by: waterWang water.wang@users.noreply.github.com

Closes FinChippay#605

Signed-off-by: waterWang <water.wang@users.noreply.github.com>
@github-actions github-actions Bot added the needs-review PR ready for Greptile AI code review label Aug 26, 2026
@github-actions

Copy link
Copy Markdown

🤖 Greptile AI Code Review

Greptile will automatically review this PR (12 file(s) changed).

Review gates:

  • ✅ CodeQL Security Scan
  • ✅ Custom rules (.greptile/config.json)
  • ✅ Architecture guidelines (.greptile/rules.md)

To manually trigger a re-review, comment @greptileai on this PR.
To skip review, add the skip-review label.

@Topmatrixmor2014

Copy link
Copy Markdown
Contributor

FIX THESE CONFLICTS

@Topmatrixmor2014

Copy link
Copy Markdown
Contributor

resolve conflicts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-review PR ready for Greptile AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue #45 — Portfolio Tax & Cost-Basis Reporting

2 participants