Skip to content

[#503] Profile page — reader portfolio and token holdings#508

Merged
realproject7 merged 4 commits intomainfrom
task/503-profile-reader-portfolio
Mar 24, 2026
Merged

[#503] Profile page — reader portfolio and token holdings#508
realproject7 merged 4 commits intomainfrom
task/503-profile-reader-portfolio

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Rewrote Portfolio tab to show actual on-chain token holdings via balanceOf multicall
  • Per-token metrics: story title, token balance, current value (via priceForNextMint), entry price (from first mint in trade_history), last traded date, genre
  • Total portfolio value displayed in $PLOT equivalent
  • Holdings sorted by most recently traded, then largest position
  • Donation history section: donations given as reader with aggregate total
  • Enhanced empty state for addresses with no holdings or donations

Test plan

  • Visit a profile with token holdings — verify balance, value, entry price display
  • Verify total portfolio value sums correctly
  • Visit a profile with donations — verify donation history shows
  • Visit a profile with both holdings and donations — verify both sections render
  • Visit a profile with no holdings or donations — verify empty state
  • Verify holdings sorted by most recent trade first

Fixes #503

🤖 Generated with Claude Code

- Query on-chain token balances via balanceOf multicall for all
  storyline tokens, filtered to non-zero holdings
- Per-token metrics: story title, token balance, current value (from
  priceForNextMint), entry price (from first mint in trade_history),
  last traded date, genre
- Total portfolio value in $PLOT equivalent
- Sorted by most recently traded, then largest position
- Donation history: donations given as reader with totals
- Enhanced empty state for addresses with no holdings

Fixes #503

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown

vercel Bot commented Mar 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
plotlink Ignored Ignored Mar 24, 2026 7:32pm

Request Review

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The holdings list and portfolio value look close, but the Portfolio tab still omits one of the issue's required data points: aggregate donations received as writer.

Findings

  • [medium] PortfolioTab only queries donations where donor_address = address, so it implements donations given but never surfaces the required aggregate donations received as writer. Because hasDonations is based only on that reader-side query, a writer who has received donations but has no holdings and has never donated will incorrectly see the empty state even though the ticket requires writer donation totals in this tab.
    • File: src/app/profile/[address]/page.tsx:650
    • File: src/app/profile/[address]/page.tsx:674
    • Suggestion: Add a writer-side donations-received aggregate for the profiled address's storylines and include it in the Portfolio tab/empty-state logic.

Decision

Requesting changes because issue #503 explicitly requires donation history to include donations given as reader plus aggregate donations received as writer, and the current implementation only covers the reader side.

Instead of fetching all storylines and multicalling balanceOf for every
token, first query trade_history for storylines the user has actually
traded, then scope the balanceOf multicall to only those tokens. This
keeps the query bounded as storyline count grows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The scoped holdings multicall fix looks fine, but the Portfolio tab still omits the issue's required aggregate donations received as writer.

Findings

  • [medium] PortfolioTab still only queries donations where donor_address = address, so it covers donations given but never surfaces the required writer-side donations received aggregate. Because hasDonations still depends only on that reader-side query, a writer who has received donations but has no holdings and has never donated will still hit the empty state.
    • File: src/app/profile/[address]/page.tsx:661
    • File: src/app/profile/[address]/page.tsx:683
    • Suggestion: Add a donations-received aggregate for the profiled address's storylines and include it in the Portfolio tab plus empty-state logic.

Decision

Requesting changes because issue #503 requires donation history to include donations given as reader plus aggregate donations received as writer, and the current implementation still only covers the reader side.

- Query storylines written by address, then sum donations received
  across all of them
- Show "Donations Received" summary card with total amount and count
- Empty state now considers donations received (writer who received
  donations but has no holdings no longer hits empty state)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The writer-donations aggregate is fixed, but the holdings query is now too narrowly scoped: it only checks tokens for storylines present in the address's trade_history. That means the Portfolio tab can miss real holdings and therefore does not satisfy the ticket's requirement to show all storyline tokens the address holds.

Findings

  • [high] PortfolioTab only multicalls balanceOf for storylines that already appear in trade_history for the address. The issue requires showing all storyline tokens the address currently holds, and the existing reader portfolio pattern scans all storylines before filtering by on-chain balance. The new bounded query will miss holdings acquired outside the indexed trade path (for example transfers or any other source not represented in that address-scoped trade_history).
    • File: src/app/profile/[address]/page.tsx:561
    • File: src/components/ReaderPortfolio.tsx:29
    • Suggestion: Follow the existing ReaderPortfolio pattern here: scan all eligible storylines, then filter by balanceOf > 0, rather than prefiltering by trade_history ownership assumptions.

Decision

Requesting changes because the current implementation can omit real token holdings and therefore does not meet issue #503's core portfolio requirement.

Revert to scanning all non-hidden storylines with tokens (matching the
existing ReaderPortfolio pattern) to catch holdings acquired via direct
transfers or other paths outside the indexed trade history.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The portfolio tab now covers the required reader holdings, portfolio value, donations given, and aggregate donations received as writer. The holdings query again matches the existing reader-portfolio pattern, so transferred or otherwise externally acquired holdings are no longer missed.

Findings

  • None.

Decision

Approve because the portfolio tab now satisfies issue #503's core requirements and my prior requested change is resolved.

@realproject7 realproject7 merged commit 22a60ee into main Mar 24, 2026
5 checks passed
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.

Profile page — reader portfolio and token holdings

2 participants