How Fomo Api calculates Solana wallet PnL (and why coverage matters)
The methodology behind Fomo Api's realized PnL: FIFO cost basis, historical USD pricing, coverage as part of the number, and why we return null instead of guessing.
Published September 22, 2026 · 6 min read
Two products can look at the same wallet and publish PnL figures that differ by an order of magnitude. Neither is lying; they're measuring different things. This is what Fomo Api measures, and what it refuses to.
Realized, not mark-to-market
realizedPnlUsd counts profit and loss from positions the wallet actually closed inside the window. A token bought and still held contributes nothing until it's sold. This is the conservative definition — it can't be inflated by a token that pumped this morning and hasn't been sold — and it's the one that matches what a trader could have withdrawn.
Some leaderboards report a blended number: realized plus the unrealized mark-to-market value of open positions. That figure is useful, but it's a different figure, and it moves every time price moves. If you're comparing our numbers with another provider's and they don't match, check which definition they use first.
FIFO cost basis
Every buy creates a lot: quantity plus USD cost at that moment. Every sell consumes the oldest open lots first (first-in, first-out) and realizes the difference between sale proceeds and those lots' cost. Lots and fills are persisted, so a wallet's PnL is reproducible, and a re-run over the same data produces the same answer.
USD pricing at trade time
Each leg of a swap is priced in USD at its block time from historical price data, with more than one source behind it. When no reliable price exists for a token at that moment, the trade is not priced at zero — it's flagged unpriced and counted against coverage.
Coverage is part of the number
A PnL figure without a coverage figure is a guess dressed up as a fact. coveragePct tells you what share of a wallet's activity the PnL is based on — trades we've ingested and priced versus trades we know exist. The public leaderboard only ranks wallets whose window PnL is complete at or above a coverage floor, so a page can end before limit: that's the full ranked set, not a truncated one.
Null means unknown
When a metric can't be computed with enough confidence, the field is null. Not zero, not an estimate. A UI that renders our data should treat null as "—". This one rule prevents a whole class of embarrassing $0.00 rows.
Source vs venue
A trade's venue is where it executed — Jupiter, Pump AMM, Raydium, OKX DEX. Its source is where it originated — a trading bot, a wallet app, a direct program call. Most APIs collapse these; we keep both, because "which bots' users are profitable" and "which venues are profitable" are different questions.
What we don't do
- We don't read another analytics product's PnL and re-serve it. Our data path is chain → our ingestion → our analytics → you.
- We don't infer social identities from wallet behaviour. Identity is an enrichment on a row, never a gate.
- We don't round coverage up. If it's 62%, it says 62%.
See the fields in practice in the wallet PnL quickstart, or start with the docs.