Wallet

FIFO cost-basis PnL with daily curve

Full per-wallet PnL: realized + unrealized SOL, profit factor, max drawdown, avg + median hold minutes, daily UTC PnL curve, closed positions sorted by pnl desc (with ROI %, hold minutes, win/loss/breakeven), and open positions hydrated with current prices from market-cap tracker.

Caching: stored in wallet_analyses with dynamic TTL — 5 min for wallets active in last 24h, 1h for 1-7d old, 24h for dormant. Every hit is validated against the wallet's trade head (audit F16): a wallet that traded after the cached analysis is recomputed (cache_invalidated: new_activity), so a resumed dormant wallet never gets a day-old answer. cache_age_seconds + computed_at carry the source age on a hit. Cache hits don't count against your daily quota.

Honesty note: two limits, both disclosed in the response. (1) Time — cost basis is only observable inside our 90-day data window, and capture itself starts 2026-04-12; a wallet that sold tokens bought before that has the overflow silently discarded rather than fabricated (notes.cost_basis_observable_from surfaces the cutoff). (2) Token universe — persisted trades are gated to the launchpad pipeline (pump.fun, LaunchLab/bonk, bags), so a wallet trading outside it is not partially covered but uncovered. The coverage object reports in_scope; when it is false, zero and empty results mean 'not captured', not 'no activity'. PRO+.

get/wallet/{address}/pnl

Request

  • Base URL: https://madeonsol.com/api/v1
  • URL: https://madeonsol.com/api/v1/wallet/{address}/pnl
  • Auth: HTTP bearer

Path parameters

addressstring required
Example:2FxiPRPLYX3H84FZkdRiUHDgDm4U5u98etbL4yvZ3qRq

Response

OK

addressstring
window_daysinteger
completeness'complete' | 'incomplete'

incomplete when at least one disposal's realized PnL is unknown (a sell whose proceeds provably went to another wallet, price_status proceeds_unattributed; or a trade with unknown consideration). Such a disposal consumes the FIFO lots (holdings are right) but is excluded from realized_sol, wins/losses, win_rate, profit_factor and best/worst — never booked as 0 proceeds. Absent on analyses cached before this field existed. This is realized-PnL completeness. It is NOT coverage.completeness (source-coverage verification: verified / not_verified / ...), which says whether the trade capture for this subject is proven complete.

incomplete_reasonsstring[]

Empty when complete.

cache_hitboolean

true when served from wallet_analyses cache

computed_atstring date-time

Always returned — when the analysis was computed (the fresh compute time on a miss, the cached row's analyzed_at on a hit)

cache_age_secondsinteger

Seconds since computed_at — the source age survives a cache hit (0 on a fresh compute)

cache_validation'head_checked' | 'unverified'

Cache hits only (audit F16): head_checked = the wallet has no persisted trade newer than the analysis watermark, so the cached analysis is current; unverified = the trade-head probe failed and the unexpired cache was served flagged. A hit whose wallet traded after the watermark is never served — it is recomputed.

cache_invalidated'new_activity'

Present on a recompute that happened because a cached analysis existed but the wallet traded after it

ttl_secondsinteger

Only present on cache misses — TTL for this row in wallet_analyses (5min / 1h / 24h based on activity)

Changes

No recorded changes to this operation across all 2 revisions of this API.