DEX volume on Solana is calculated by decoding every swap instruction in a slot range, reading the realised token amounts out of each transaction's balance records, converting those amounts into one common quote asset, and summing the result over a stated window. Everything after that step — venue set, side convention, route handling, fee treatment — is a policy decision, not arithmetic.
Those policy decisions are where two honest systems separate. The chain is a single shared record, so there is exactly one set of facts underneath every dashboard. The disagreement lives entirely in the collection layer. This note walks that layer end to end: what a pool execution actually records, how the four families of indexing infrastructure read it, where routes inflate a total, what happens to failed attempts, and how fees sit inside or outside the published number.
Pool-level accounting
The unit of account is the pool fill, not the user's intention. A swap instruction directs an automated market maker program to move tokens between two token accounts and update its reserves. On a constant-product pool the reserves obey the invariant x × y = k, so the output for a given input is determined entirely by the reserve balances at that instant. Two fills of identical size against the same pool minutes apart will produce different outputs.
An indexer should not trust the arguments carried by the instruction. A swap instruction typically encodes a requested input amount and a minimum acceptable output, which is a protection parameter rather than a result. The realised amounts appear only after execution, in the pre-token-balance and post-token-balance records attached to the confirmed transaction. Reading those deltas is the difference between recording what was asked for and recording what settled.
Scaling matters before any sum is taken. Native SOL is denominated in lamports with nine decimals, and every SPL mint declares its own decimal count, so raw integer deltas from two different mints are not comparable until each is divided by its mint's scale. Wrapped SOL adds a further wrinkle: a swap that appears to consume native SOL usually moves the balance of a temporary wrapped-SOL token account that is created and closed inside the same transaction.
Pricing the fill is the last accounting step. A leg can be priced from itself, using the ratio of the two realised amounts, or from an external reference series for the quote asset. Self-pricing is internally consistent and immune to reference-feed lag, but it means a single distorted fill enters the total at its own distorted price. Reference pricing is more stable and imports the granularity, and the errors, of whatever price series was chosen. The broader question of what the resulting figure represents is treated in the note on the anatomy of Solana trading volume.
How indexers differ
Four families of infrastructure produce nearly all published Solana volume figures, and each family has a characteristic blind spot. Understanding which family a number came from usually explains more of the disagreement than any argument about methodology.
Raw RPC parsing is the most direct. A client requests confirmed blocks with full transaction detail and decodes them locally, either live or as a backfill over a historical slot range. The Solana RPC documentation describes the block and transaction payloads involved. The method is deterministic and fully auditable, because every figure traces back to a transaction signature that anyone can re-fetch. It is also the slowest to produce and the heaviest in bandwidth, since full blocks are large and most of their contents are irrelevant to a single pair.
Streaming and webhook pipelines invert the trade-off. A validator plugin or a provider webhook pushes account and transaction updates as they are produced, which brings observation latency close to the chain's own progression — Solana targets a slot roughly every four hundred milliseconds. The characteristic weakness is delivery. Push systems are at-least-once at best, they can drop messages during provider incidents, and the resulting holes are invisible unless the pipeline separately verifies that every slot in the range was actually seen. A streaming total that has never been reconciled against a block-range backfill is an estimate.
Tracker APIs return figures that are already aggregated. They are inexpensive, they cover a wide venue set without integration work, and they answer in one request what a raw pipeline needs hours to compute. The cost is that the conventions are fixed by the vendor and rarely documented to the level a reconciliation requires. A tracker cannot tell you whether the number in front of you collapsed a two-hop route, and no amount of downstream processing can recover that detail from a scalar.
Chain-data warehouses sit between the two. Decoded transaction and instruction tables are exposed through SQL, so a figure can be re-derived, sliced by program, and audited against its constituent rows. The blind spot is decoding coverage: a warehouse can only decode programs whose interface definitions someone has already added, so a venue deployed last week may be entirely absent from a query that otherwise looks complete. Whether that absence matters depends on the pair, a point developed in the survey of where Solana volume comes from.
Double counting through routes
Most Solana trading passes through an aggregator, which selects a path across one or more pools and may split a single order between them. The routing behaviour and the venue set are described in the aggregator's developer documentation. A routed trade is a single user action that produces several genuine pool executions, and both descriptions are true at once.
The inflation appears when the two descriptions are added together. Summing pool-level executions counts the intermediate leg as its own trade, because at pool level it was one. Nothing is being fabricated: the intermediate pool really did receive an input and really did pay an output. But a reader who takes the sum as a measure of demand for the final token has counted a mechanical transfer as an expression of interest.
Illustrative arithmetic
The amounts and the fee rate below are invented round numbers chosen to make the relationship visible in one line. They measure nothing real, they are not the parameters of any pool, and no venue charges the rate used here.
Take a user who submits 60 SOL and receives a token through a two-hop path: SOL into a stable quote asset, then that quote asset into the target. Assume a flat one percent trading fee on each hop. The first pool records a 60 SOL execution. The second pool receives 59.4 SOL of value and records that. A pool-level sum reports 119.4 SOL, or 1.99 times the user's actual commitment, while an aggregator-level count reports 60 SOL. Both are correct answers to different questions.
The practical rule follows directly. Pool-level sums answer questions about where liquidity is being consumed and which venues bear execution flow. Aggregator-level counts answer questions about user behaviour. The two must never be added, and a figure that does not state which one it is cannot be compared to anything. The same rule decides how to read the output of any tool that submits orders on your behalf: a Solana DEX volume bot routing through an aggregator will show a larger pool-level sum than the SOL it actually committed, and treating that inflated figure as the result is the single most common accounting error in this area.
Failed and reverted transactions
A Solana transaction either commits every one of its state changes or none of them. When an instruction returns an error the runtime discards the whole transaction's writes, yet the transaction is still recorded in the ledger with a non-null error field and the fee payer is still charged. That combination is what makes failed swaps a live source of counting error.
Three failure modes dominate on a busy pair. The realised output falls below the minimum specified by the trader, so the program aborts on the slippage check. The transaction exhausts its compute unit budget before the swap completes. Or a Token-2022 mint carries a transfer hook whose additional program logic rejects the transfer, so a swap that would have succeeded against a plain SPL mint fails against this one. In every case no balances moved.
The vulnerable pipelines are the ones that parse program logs rather than balance deltas. Logs are emitted during execution, before the outcome is known, so a naive log parser can extract an amount from a transaction that ultimately reverted. Pipelines built on pre and post token balances are structurally immune, because a reverted transaction has identical pre and post values and therefore contributes a delta of zero.
Failed attempts are still worth collecting, just not in the volume column. Attempt counts and landing rates describe how expensive a pair is to trade and how much competition exists for the same reserves, which is genuinely useful when assessing an execution strategy. Keeping them in their own metric is one of the standing recommendations in the note on measuring a volume campaign. Any individual case can be verified in a block explorer such as Solscan, where the transaction status is shown alongside the balance changes.
Fee-inclusive and fee-exclusive notional
A swap carries several distinct charges and they do not all belong in the same place. The liquidity provider fee is deducted from the input before the remainder is applied to the pricing curve, and it accrues to the pool. A protocol fee, where a venue operates one, is a further deduction from the same input. An interface or aggregator fee may be taken separately, outside the pool entirely. And the transaction fee plus any priority fee is a network cost paid in SOL that has nothing to do with the traded pair at all.
Only the first two sit inside the swap notional in any meaningful sense, and even then the treatment is a choice. A fee-inclusive figure counts what the trader committed and is the right basis when the question is about capital deployed. A fee-exclusive figure counts what actually reached the invariant and is the right basis when the question is about price formation, because the fee portion never participated in the curve.
Illustrative arithmetic
The trade size, the fee rate and the trade count below are invented to demonstrate how the two treatments diverge as turnover rises. They are not measurements, and the fee rate does not correspond to any real venue.
Suppose a single trade commits 200 SOL against a pool charging a flat one percent fee. Two SOL is retained as the fee and 198 SOL reaches the curve. On one trade the two treatments differ by 2 SOL, which nobody would notice. Across 500 identical trades in a window, the fee-inclusive total is 100,000 SOL and the fee-exclusive total is 99,000 SOL, a gap of 1,000 SOL. The percentage gap is constant; the absolute gap scales with turnover, which is exactly why it surfaces first on the pairs with the heaviest cycling.
The reconciliation implication is that fee treatment should be tested before more exotic explanations are considered. If two sources disagree by a small, stable percentage that does not move with the venue mix, fee handling is the first hypothesis, and it is cheap to confirm on a single known transaction.
Comparing collection methods
The following comparison summarises what each family reads, how quickly it can see an event, what it structurally fails to capture, and what it costs to operate. The cost column is deliberately qualitative: the shape of the cost curve is stable across providers even though the prices are not.
| Method | What it reads | Latency character | What it systematically misses | Cost character |
|---|---|---|---|---|
| Raw RPC parsing | Confirmed blocks with full transaction detail, decoded locally | Bounded by request throughput; historical backfill runs at whatever rate the endpoint allows | Nothing structurally, provided every slot in the range is fetched; gaps appear only from skipped requests | High bandwidth and engineering time, low trust requirement |
| Streaming and webhook pipelines | Pushed account and transaction updates from a validator plugin or provider | Close to chain progression, which targets a slot roughly every 400 milliseconds | Events lost during provider incidents, and any slot never delivered, unless slot continuity is separately verified | Moderate and continuous; scales with subscription breadth |
| Tracker APIs | Pre-aggregated figures published by a vendor | Whatever refresh interval the vendor operates; not observable from the outside | The conventions themselves — side counting, route collapsing and venue coverage are not recoverable from the returned scalar | Low per query, no infrastructure, full trust requirement |
| Chain-data warehouses | Decoded instruction and transaction tables queried with SQL | Ingestion lag measured in minutes to hours, depending on the provider | Programs whose interface definitions have not yet been added, so recently deployed venues can be silently absent | Query-metered; cheap to explore, expensive to run at high frequency |
| Aggregator-reported feeds | User-facing trades as recorded by the routing interface | Near real time for that interface only | All activity that did not pass through that particular interface, including direct pool interaction | Low, but coverage is narrow by construction |
One pattern is worth naming. Auditability and latency pull against each other. The method that lets you prove a figure is the slowest to produce it, and the method that sees an event first is the one most likely to have missed a different event without telling you. Serious desks run two families in parallel and treat the disagreement between them as a monitored quantity rather than an embarrassment.
Reconciling two sources
When two figures disagree, the goal is not to decide which is right. It is to decompose the gap into named components until the residual is small and explained. The following sequence does that with the minimum amount of work, and it stops as soon as the difference is accounted for.
- Fix the window in slotsConvert both sources to the same slot range rather than the same clock time. Block times are approximate and bucket boundaries drift, so a clock-aligned comparison carries an unquantified error before anything else is examined.
- Fix the venue setList every program each source counts for the pair. A venue present in one list and absent from the other explains a gap immediately and requires no further arithmetic.
- Pull the raw transaction setFetch the confirmed transactions in the slot range for the pair's pools directly, so the reconciliation has an independent third figure rather than two competing claims.
- Recompute from balance deltasDerive amounts from pre and post token balances, scaled by each mint's decimals. This removes log-parsing artefacts and, by construction, excludes every reverted transaction.
- Produce both route figuresCompute the pool-level sum and the route-collapsed sum from the same raw set. Their ratio tells you how much routing activity the pair carries and which of the two candidate figures each source resembles.
- Test the side conventionTake one transaction with a known input, locate it in each source's trade feed, and compare. A reported value near twice the input means both legs are being summed.
- Normalise fee treatment and quote pricingStrip trading fees from both totals, or add them to both, and price the quote asset from the same series at the same granularity. A small stable percentage gap usually dissolves here.
- Attribute the residualWrite down what remains and name its cause. An unattributed residual, however small, means the reconciliation is unfinished and neither figure should be quoted as settled.
A reconciliation note is worth keeping even when the answer is boring, because the same pair of sources will disagree again and the second investigation should not start from zero. At minimum the note should record the slot range examined, the venue lists compared, the side convention observed in each source, the route treatment each one applies, and the size and cause of the residual. Five lines are usually enough.
None of this makes any single source untrustworthy. It makes each source a measurement with a stated method, which is the only form in which a volume figure carries information. A number without a method behind it is not wrong; it is simply not yet a claim about anything.
Method questions we get asked
How is DEX volume calculated on Solana, in one sentence?
Swap instructions in a slot range are decoded, realised amounts are read from each transaction's pre and post token balances, every fill is converted into one quote asset, and the results are summed. The conventions applied on top of that sum are what make two correct implementations produce two different numbers.
Can I use transaction logs instead of balance deltas?
You can, but the pipeline then has to filter reverted transactions explicitly, because logs are emitted during execution and survive a revert. Balance deltas handle that case for free, since a reverted transaction leaves identical pre and post values and contributes nothing.
Why does route collapsing matter so much on Solana specifically?
Because aggregated routing carries a large share of retail flow, and routers split orders across venues to reduce price impact. On a chain where most users trade directly against a single pool the two figures would nearly coincide; here they routinely do not.
Does a higher-latency method produce a less accurate total?
No. Latency and completeness are independent properties. A slow block-range backfill is the most complete method available, while a low-latency stream can be simultaneously fast and missing an hour of events it never received.
How do I check whether a source excludes failed transactions?
Find a pair during a period of congestion, where failures are common, and compare the source's trade count against the count of successful swaps you derive from the raw transaction set. A meaningful excess suggests attempts are being counted.
Is there a single correct volume number for a token?
No, and treating one as canonical is the underlying error. There is a correct number for a fully specified question: this venue set, this slot range, this side convention, this route treatment, this fee basis. Change any term and the correct answer changes with it.
Filed under Market structure. Corrections and method questions go to the desk; our sourcing rules are on the editorial policy page.