Kyvora

Docs

Everything Kyvora shows is computed in your browser from public chain data. This page describes exactly how.

01Data sources

  • Solana RPC — getSignaturesForAddress (paginated, 1,000 per page) and getTransaction (jsonParsed, version 0). Defaults to the public mainnet endpoint; set RPC_MAINNET or HELIUS_API_KEY for a faster one.
  • Jupiter lite APIs — current token prices (Price v3) and token metadata (Tokens v2).
  • DexScreener — fallback for prices and metadata. Metaplex on-chain metadata is the last fallback; otherwise the shortened mint is shown. Names are never invented.

Parsed swaps are cached per wallet in your browser (IndexedDB), so re-opening a wallet only fetches new signatures.

02Swap detection

For each successful transaction where the wallet is a signer, Kyvora computes balance deltas for the wallet:

  • Per-mint token deltas from preTokenBalances / postTokenBalances where the owner is the wallet (SPL Token and Token-2022).
  • Native SOL delta from preBalances / postBalances, with the transaction fee added back if the wallet paid it, so the fee is not double counted.
  • WSOL is treated as SOL: wrapped SOL deltas are added to the native delta.

One non-quote token moving in against SOL, USDC or USDT moving out is a buy; the reverse is a sell. Two non-quote tokens moving in opposite directions with no quote movement are recorded as a sell of one plus a buy of the other, valued in USD. Pure transfers, airdrops and account rent are not trades. Venue labels come from program IDs (Jupiter, Raydium, Orca, Meteora, Pump.fun, PumpSwap), otherwise "Other DEX".

03PnL, FIFO vs average cost

FIFO: a sell consumes the oldest buy lots first; the cost of consumed lots is the cost basis. Average cost: all lots merge into one, and a sell uses the running average.

realized = proceeds − cost of tokens sold

net PnL = realized − network and priority fees

unrealized = quantity held × live price − remaining cost

A round-trip trade starts when a position opens from zero and closes when the held quantity returns to about zero (below 0.1% of its peak). Hold time is close time minus open time. Win rate = closed trades with net PnL > 0 divided by all closed trades. ROI = realized ÷ cost of the tokens sold.

04Fees and WSOL

Each swap transaction's meta.fee (base plus priority fee) is shown separately and subtracted from PnL. Fees are counted once per transaction. Rent deposited to or reclaimed from token accounts shows up in the SOL delta of the transaction it occurs in.

05Pricing caveats

Chain history gives exact amounts, not historical prices. When a swap has a stablecoin leg, its USD value is exact and its SOL value is derived from the current SOL price. When it is quoted in SOL, its SOL value is exact and its USD value uses the current SOL price. Such values are marked est. Token-to-token swaps are valued at current prices and are always estimates. Unrealized PnL needs a live price; positions without one are counted as unpriced and left out of totals.

06Known limits

  • Public RPC nodes rate-limit and may not serve deep history. Transactions that fail to load are reported and excluded.
  • A wallet is analysed for up to 5,000 transactions per request.
  • Sells with no matching buy in the selected range (tokens received by transfer, or bought before the range) are excluded and counted.
  • Multi-hop or multi-token transactions that do not reduce to one token against one quote leg are not classified.
  • Transfers are not trades. Moving tokens between your own wallets is not a realized event; use a wallet group to merge them.

07API routes

  • GET /api/signatures?address=&before=&until=&limit=
  • POST /api/transactions with { signatures: string[] } (max 100)
  • GET /api/prices?ids=mint,mint
  • GET /api/tokens?mints=mint,mint
  • GET /api/sol-price
  • GET /api/rpc-status

All inputs are validated with Zod, upstream calls time out after 10 seconds, responses are cached for 60 seconds and each IP is rate limited. Server keys are never sent to the client.

Computed from on-chain data. Prices for old trades are estimates when noted; verify the linked transactions.