Skip to content

[GF-14] [FRONTEND] Portfolio & Positions Page #46

@wumibals

Description

@wumibals

Overview

⚠️ Depends on: #42 (GF-09 — Wallet Integration) and #44 (GF-12 — Data Service Layer).

Build the portfolio page — the primary logged-in view showing a user's active positions, accrued yield, lock countdowns, and available actions. This is the page users will return to most often after depositing.

Problem

No portfolio view exists anywhere in the app. After a user deposits, there is no way for them to:

  • See their positions
  • Track accrued yield
  • Know when their lock expires
  • Withdraw or early exit

The dashboard (app/src/app/dashboard/page.tsx) only shows static vault tier info, not user-specific position data.

Proposed Solution

Create app/src/app/portfolio/page.tsx

Portfolio summary card (top of page)

  • Total USDC deposited across all tiers
  • Total accrued yield (live, updating)
  • Blended APY across all positions
  • Number of active positions

Position cards (one per active tier)
Each position card shows:

  • Tier name and share multiplier
  • Principal deposited
  • Shares held
  • Accrued yield (calculated from share value delta since deposit, updating every 30 seconds)
  • Lock expiry: either Unlocked (Flex) or a countdown: Expires in 47 days with the exact date
  • Withdraw button — enabled only when current_ledger >= lock_until (or always for Flex); calls sdk.withdraw({ tier }) from GF-08
  • Early Exit button — always shown for locked tiers; shows the fee and net amount in a confirmation modal before submitting; calls sdk.earlyExit({ tier })

Yield history chart
A simple line chart (use recharts or chart.js) showing cumulative yield earned over time per position, using harvest event history from the data layer (GF-12).

CSV export
A Download CSV button that exports a table of all transactions (deposits, withdrawals, harvests attributed to the user) for tax reporting purposes. Columns: date, type, tier, amount, tx hash.

Empty state
If the wallet has no positions, show an encouraging empty state with a Deposit Now link to /deposit.

Navigation
Add a Portfolio link to the main nav (visible only when wallet is connected).

Acceptance Criteria

  • /portfolio page exists and requires wallet connection (redirects to connect flow if not connected)
  • All active positions are shown with live principal, shares, and accrued yield data
  • Lock expiry displayed as a human-readable countdown and exact date
  • Withdraw button is disabled before lock expiry and enabled at maturity
  • Early Exit button shows fee and net amount in a confirmation modal before submitting
  • Both withdraw and early exit actions show pending/confirmed/failed tx states
  • Portfolio summary card shows aggregate totals across all tiers
  • Yield history chart renders for positions with at least one harvest event
  • CSV export downloads a valid file with correct columns and data
  • Empty state shown when wallet has no positions

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions