Wallet PnL
Realized + unrealized profit & loss for a wallet — per token and aggregate — from its swaps on the tokens we index. Cost basis is average-cost by default (?basis=fifo for lot-matched), priced at each swap's block time; open positions are valued at the current reconciled price (Jupiter fallback) and cross-checked against the wallet's actual on-chain balances.
Path parameters
| Field | Type | Description |
|---|---|---|
addressrequired | string | Wallet address. |
Query parameters
| Field | Type | Description |
|---|---|---|
basisoptional | avgcost | fifo | Cost-basis method: average-cost (default) or FIFO lot-matching. default avgcost |
gasoptional | on | off | on subtracts an ESTIMATED network fee per indexed swap from realized PnL, valued at block-time SOL/USD (the swaps table carries no per-tx fee, so gas is an estimate). default off |
reconcileoptional | true | false | Cross-check replay positions against the wallet's actual on-chain token balances. false skips the RPC read; summary.reconciled reports whether it ran. default true |
formatoptional | csv | format=csv downloads the per-token reconciliation as a CSV artifact instead of JSON. |
networkoptional | mainnet | devnet | Network to read. Devnet returns an empty payload (with a note) until its ingestor lands. default mainnet |
Response fields
| Field | Type | Description |
|---|---|---|
basis | avgcost | fifo | Cost-basis method used for this response. |
gasIncluded | boolean | true when realized PnL is gas-inclusive (gas=on with a configured per-swap estimate). |
summary.realizedPnlUsd / unrealizedPnlUsd / totalPnlUsd | number | Aggregate PnL across indexed tokens. When summaryComplete is false, totalPnlUsd is a FLOOR estimate (unpriced open positions contribute $0). |
summary.roiPct | number | null | totalPnl / total invested, %. |
summary.winRate | number | null | % of closed positions (those with a sell) that were profitable. |
summary.totalInvestedUsd / totalProceedsUsd / totalVolumeUsd | number | USD bought / USD sold / total traded. |
summary.tokensTraded / tradeCount / openPositions / pricedOpenPositions | number | Counts (openPositions = tokens still held; pricedOpenPositions = those with a current price). |
summary.basis | string | Cost-basis method used (avgcost or fifo). |
summary.totalGasUsd | number | Total estimated gas subtracted from realized PnL (0 unless gas=on). |
summary.nonTradeInflowTokens | number | Tokens whose sold quantity exceeded their bought quantity (likely transfer/airdrop inflows). |
summary.reconciled | boolean | true when positions were verified against on-chain balances; false when reconcile=false or the RPC read failed/timed out. |
summary.balanceMismatchTokens | number | Tokens whose replay position disagreed with the on-chain balance (dust-tolerant). |
summary.summaryComplete | boolean | false when any open position lacks a current price — summary totals are then a floor estimate. |
summary.unpricedOpenPositions / unpricedCostBasisUsd | number | Open positions with no current price, and the cost basis sitting in them (excluded from unrealized PnL). |
summary.priceCapExceeded | boolean | true when the wallet traded more distinct mints than the price-lookup cap — mints beyond it have no current price. |
summary.stalePriceMints | number | Open priced positions whose price was last observed more than 10 minutes ago. |
truncated | boolean | true when swap history hit the replay cap (oldest swaps kept for cost-basis correctness) — later activity is NOT reflected. |
truncatedAt | string | null | Timestamp (ISO) of the last swap included when truncated; null otherwise. |
unindexedHoldings[].mint | string | A chain holding with zero swaps in our index — listed with no PnL claims. The array itself is null when reconciliation was skipped or failed. |
unindexedHoldings[].uiAmount | number | On-chain balance of that holding (ui units; native SOL is folded into wSOL). |
tokens[].realizedPnlUsd | number | Per-token realized PnL (gas-inclusive when gas=on). |
tokens[].unrealizedPnlUsd / totalPnlUsd | number | null | Per-token unrealized / total PnL — null when an open position can't be priced. |
tokens[].avgBuyPriceUsd / avgSellPriceUsd | number | null | Weighted average entry / exit price. |
tokens[].heldQty / costBasisUsd | number | Open position size (replay) and its remaining cost basis. |
tokens[].heldValueUsd | number | null | Value of the open position — null when unpriced; clamped to the chain balance when the replay over-states it. |
tokens[].partial | boolean | true if the wallet sold more than we saw it buy (incomplete pre-index history). |
tokens[].coverage | number | null | Fraction of sold quantity with a swap-derived cost basis, in [0,1]; null when nothing was sold. |
tokens[].nonTradeInflow | boolean | true when part of the position arrived off-book (transfer/airdrop) — sold more than bought, or the chain holds more than the replay accounts for. |
tokens[].gasUsd | number | Estimated gas (USD) already subtracted from realizedPnlUsd (0 unless gas=on). |
tokens[].chainBalance | object | null | The wallet's actual on-chain balance ({ amountRaw, uiAmount }; native SOL folded into wSOL); null when reconciliation skipped/failed. |
tokens[].balanceMismatch / clampedUnrealized | boolean | balanceMismatch: replay vs chain disagree beyond dust. clampedUnrealized: the replay held MORE than the chain (a sell happened off our index) — the valued quantity was clamped and the un-held portion's outcome left out rather than guessed. |
tokens[].priceAsOf | string | null | When the current price was last observed (ISO) — staleness disclosure for unrealized PnL. |
tokens[].indexedSince | string | null | Earliest swap we hold for this mint — "all-time" PnL starts here, not at the token's launch. |
tokens[].note | string | null | Per-token caveat — e.g. the native-SOL read failed so wSOL was excluded from balance reconciliation this response. null otherwise. |
Covers only the tokens this instance indexes; attribution is by transaction fee-payer (a bot fee-payer is not necessarily the trader). Cost basis is average-cost by default; ?basis=fifo gives lot-matched FIFO accounting.
Positions are reconciled against the wallet's ACTUAL on-chain balances by default. If the replay holds more than the chain (a sell happened off our index), the valued quantity is clamped and flagged (clampedUnrealized) instead of reporting phantom unrealized PnL; if the chain holds more, nonTradeInflow is set. Chain holdings we never saw trade are listed under unindexedHoldings with no PnL claims.
summary totals are a FLOOR estimate when summaryComplete is false: open positions without a current price contribute $0 (see unpricedOpenPositions / unpricedCostBasisUsd / priceCapExceeded). "All-time" means since we indexed each mint (tokens[].indexedSince), and very large histories are capped oldest-first — truncated/truncatedAt disclose when later activity is not reflected.