Gathering Evidence From Chain Data: A Collection Method

Most weak volume readings fail at collection rather than at interpretation. This page sets out how the desk pulls chain data: writing the question before the query, defining and justifying the window, capturing raw fields instead of derived ratios, folding routed legs back into single user actions, and recording gaps rather than smoothing them so a second analyst can rerun the same pull.

Question
How should chain data be collected so that a volume reading is reproducible and can be argued with properly?
Evidence used
Raw RPC transaction records for a defined slot range: signatures, slots, block times, fee payers, signers, fees, token balance deltas, program ids, inner instructions and logs.
What it cannot show
Collection produces no verdict at all. A clean pull says nothing about intent, and a complete record of a window says nothing about the periods outside it.
Falsified by
A second analyst reruns the documented pull against the same slot range and gets a materially different transaction set that the gap log does not explain.
Confidence
High, but only about the process. The method reliably makes a pull reproducible; it makes no claim about what the resulting data means.

Collect the evidence before you interpret it. Write the question down, fix the observation window, pull raw transaction records for the pair, store the original fields rather than derived summaries, fold routed legs back into single user actions, and record every gap. That order is the whole method. Interpretation comes later, on data that has not already been shaped to fit it.

This page covers collection only. It does not rank the checks that separate produced flow from spontaneous flow, and it does not settle how a finding is phrased at the end. It covers the unglamorous middle: what you pull, in what order, what you keep verbatim, and what you log.

Write the question first

A question written after the data is a story. Once a chart has been looked at, the analyst already knows which window, which wallets and which threshold make the shape strongest, and every later choice drifts towards that picture. None of that drift feels dishonest from the inside. It feels like judgement. The defence is committing the question to the log first.

A usable question names the pair, the period, the counting unit and the observation that would answer it in the negative. The counting unit matters most: signatures, swap instructions, distinct fee payers and distinct signers all give different totals for one window. Each is defensible alone. Mixing them mid-analysis produces a number describing no real activity.

What would falsify this

If a desk reached the same reading whether the question was written before or after the pull, this concern would be overstated. The test is cheap: two analysts, one pair, one working from a pre-written question and one from a chart. If their windows, thresholds and counting units agree, order of operations matters little.

Defining the window

An arbitrary window is the commonest silent error in this work. It is silent because nothing in the output looks wrong: the counts are correct, the parser is fine, the arithmetic checks out. The error sits in the sample. A window starting where a burst starts and ending where it ends will always show a dense burst.

Defensible boundaries come from events outside the data being tested: pool creation, a migration, a listing, or a calendar block chosen in advance. State the boundary in slots as well as in time, because slots are the ledger's own index and never shift while block time is an estimate. Add a quiet margin either side, or a burst cannot be told from a baseline.

ConfidenceHigh

High confidence applies to the claim that post hoc windows bias results, not to any particular finding. The mechanism is not subtle: a boundary chosen to contain a pattern guarantees the pattern. It sits below certainty only because a pre-registered window can still be biased through venue selection or thresholds set later.

The collection order

Pull in dependency order and resist starting with the interesting part. Accounts first, then signatures, then parsed instruction data. Each stage constrains the next, and doing them out of order means re-pulling with slightly different parameters, which is how two runs of one analysis end up disagreeing without anyone able to say why.

Start with the pair and pool accounts: market address, vault or reserve accounts, mints and program ids, plus a record of how each was identified. Program interfaces are documented through the Solana documentation and the Solana Program Library, and account roles should be read from those rather than from an explorer's labels.

Then pull signatures for those accounts across the slot range, paginating to exhaustion and logging every page boundary. Only once the signature set is closed should you fetch and parse the transactions. Parsing first gives readable output early, but it parses a set whose completeness you have not established, and completeness is what the rest rests on.

  • Record the endpoint and its commitment level at every stage.
  • Freeze the signature set before parsing and store it as an artefact.
  • Note which accounts were included and which were excluded.
  • Version the parser and the deduplication rule, and log both.

Which fields to store raw

The rule is simple and unpopular: store inputs, derive outputs at read time. A derived value is a summary with its inputs discarded, so the moment a parser bug is found, every derived value becomes uncorrectable. Recomputing from stored raw fields takes seconds. Re-pulling months later may be impossible once history is pruned.

Fields the desk stores verbatim from each transaction record, and the evidence lost if only a derived value is kept.
FieldWhere it comes fromWhy it is stored rawWhat is lost if derived instead
Transaction signatureSignature query resultThe only stable identifier for the actionNothing can be re-fetched or cited; counts become unverifiable
SlotTransaction recordThe ledger's own ordering index, which never shiftsA timestamp alone loses ordering across close blocks
Block timeTransaction record, may be absentAn estimate, and its absence is informationFilling a missing value turns a known gap into a false observation
Fee payerFirst message account keyIdentifies who funded the action, which drives clusteringPer-wallet aggregates hide that many wallets shared one payer
SignersMessage header and account keysSigner sets separate delegated from direct actionA single actor field erases co-signing and authority structure
Fee in lamportsTransaction metaBase fee is 5000 lamports per signature; the rest is priorityA total cannot be split back into base and priority
Pre and post token balancesTransaction meta balancesGround truth for what actually movedNet flow destroys direction, decimals and the per-account split
Program idsInstruction recordsIdentify the venue and the routing path takenA venue label written at capture time cannot be fixed later
Inner instructionsTransaction metaExpose routed legs invisible at the top levelOuter counts undercount hops and overcount user actions
Log messagesTransaction meta logsCarry program errors and detail parsers missA success flag hides why an attempt failed, often the signal

A derived ratio shows the cost concretely. A stored buy to sell ratio looks efficient until the parser is found to have mislabelled an instruction variant, at which point the ratio can only be deleted. Storing the balance deltas behind it makes the fix a recomputation. The same holds for any score or cluster label: keep the evidence, regenerate the judgement.

Routed legs and double counting

Aggregators split one user action across several pools, so a single signature can carry several swap instructions on different venues. The naive count treats each leg as a trade. The user did one thing; reporting three is not a rounding error, because it reshapes the distribution and inflates every turnover figure. Deduplication belongs at collection time, under a written rule.

Illustrative arithmetic, invented round numbers, describing no real pair

Suppose a window returns 300 swap instructions across 150 signatures on an invented pair called PAIR-X, each user action routed through two pools. Counting instructions gives 300 trades; counting signatures gives 150. If each leg carries 400 units of notional, summing legs gives 120,000 against a user-facing 60,000. The factor of two is purely an artefact of the counting unit.

The practical rule is to reduce to the user action, keyed by signature, and store the leg detail alongside rather than instead of it. Multi-hop routing is documented well enough, for instance in the Jupiter documentation, that legs can usually be attributed to venues. Where attribution is uncertain, mark the action unattributed rather than guessing.

This does not prove a deduplicated count is right for every purpose; a venue measuring its own throughput has reason to count legs. The point is consistency and disclosure. Pick the unit matching the question, apply it to both sides of any comparison, and state it, because comparing a leg count with a signature count is meaningless.

Recording gaps honestly

Every real pull has holes. Signature queries paginate and providers cap how far back they page. Older history gets pruned, so a window available last quarter may not be now. Rate limits truncate heavy pulls midway. Block time is occasionally absent. Each is ordinary infrastructure behaviour, and each has to appear in the record.

The temptation is to smooth. Interpolating a missing block time, extrapolating across a pruned range or dropping a failed page all produce a tidier dataset that looks complete and is not. A gap written down costs a caveat. A gap smoothed away costs credibility, because observed values become indistinguishable from manufactured.

A gap entry should name the affected slot range, the reason, the provider and whether the pull was retried. Cross-checking a suspect range against an independent explorer such as Solscan turns an unknown into either a resolved gap or a confirmed one. Both outcomes beat an unmarked hole.

What would falsify this

If two independent pulls of the same slot range, from different providers, returned identical signature sets with no gap entries on either side, the concern about silent incompleteness would not apply to that window. That is testable and worth running wherever a reading is strong. Where the sets differ, the difference is evidence about the collection layer.

A reproducible pull, step by step

Reproducibility here means something modest: a second analyst, given the log entry alone, can rerun the pull and obtain the same transaction set, or can see from the gap notes why they cannot. That is the whole standard. It requires no agreement about interpretation, and the two are kept apart deliberately.

  1. Write the question. Name the pair, the counting unit, the period and the observation that would answer it negatively.
  2. Fix the window in slots. Justify both boundaries by an event outside the data, add a quiet margin, and record why.
  3. Resolve the accounts. Identify market, vault, mint and program addresses from documentation, and note the rejected candidates.
  4. Freeze the signature set. Paginate to exhaustion, log every page boundary and failed page, and store the list as an artefact.
  5. Fetch and store raw records. Keep full transaction responses verbatim, including meta, inner instructions and logs, before parsing.
  6. Apply the deduplication rule. Reduce routed legs to user actions under a named, versioned rule, keeping leg detail alongside.
  7. Reconcile and record gaps. Compare counts against a second source where a range looks thin, and log every discrepancy.
  8. Write the log entry. Record endpoint, commitment, slot range, rule versions, checksums, operator and timestamps, then stop.

The chain-of-custody note is the last three steps taken together. It is not a legal artefact and the desk makes no claim that it meets any evidentiary standard. Its purpose is narrower: to move disagreement away from the data and towards the reading, where disagreement is productive.

The evidence log schema

A log entry is one row per pull, not one per transaction, because it describes the collection event. Kept in plain tabular form it is readable by a person, diffable by a machine, and it survives the analysis tooling being rewritten. Placeholders stand in below; no real address or signature appears anywhere on this site.

Minimum columns for an evidence log entry, with anonymised examples of the kind of value each column holds.
ColumnMeaningExample kind of value
entry_idUnique identifier for this collection eventENTRY-14
question_idReference to the pre-written questionQ-3, stored before the pull
subjectAnonymised pair or market under examinationPAIR-X
venuesPrograms and pools included in scopePROGRAM-1, PROGRAM-2
slot_from and slot_toWindow boundaries in slots, with justificationTwo integers plus a one-line reason
counting_unitWhat one counted item representsUser action, keyed by signature
endpointProvider and commitment level usedRPC-A at confirmed commitment
signature_artefactStored signature list and its checksumSIGSET-4 with a hex digest
sample_referenceAnonymised pointer used in the write-upSIG-1 mapping to WALLET-A
parser_versionVersion of the instruction parser appliedPARSER-2.1
dedup_ruleNamed version of the routing reduction ruleRULE-2, legs folded by signature
gapsEvery unresolved hole, with its reasonSlot range plus pagination limit reached
operator and timestampsWho ran it and when, in UTCANALYST-1 with start and end times

Two habits make the log worth keeping. Write the entry as the pull happens, since reconstructed logs inherit the same hindsight problem as questions written after the data. And keep the anonymised pointer column disciplined, so WALLET-A means one account throughout a case file and the write-up never needs a real address.

Where the method quietly fails

The first failure is venue coverage. Activity on Solana is spread across several DEXs and routers, and any measurement covering one venue, exactly like any tool covering one venue, gives a partial picture of the same pair. Whether you are reading activity or generating it, multi-venue coverage is the first thing to check on either side of the question, which is why a service such as a multi-DEX Solana volume bot is described by its venue list first, and why a single-venue pull should carry that limitation in its log entry rather than a footnote.

The second is definitional drift across a long case. Counting units get changed mid-analysis, a threshold gets nudged, the deduplication rule gets improved halfway through. Each change is individually reasonable and the combined series is no longer comparable. Versioned rules are the cheap defence: they make drift visible as a version change rather than invisible as a better result.

The third is that collection quality has no relationship to inference quality. A meticulous dataset supports a reckless conclusion as willingly as a sloppy one, and a good log can make a weak reading look authoritative. Clean collection buys reproducibility and nothing else. What the data can carry is a separate discipline, covered in stating confidence honestly, and the same caution applies when raw fields feed wallet clustering, where one mis-parsed fee payer merges two unrelated operators.

The fourth is scope creep in the account set. Adding accounts as they start to look interesting turns a defined sample into a curated one, and the curation follows the emerging story. Treat any addition as a new pull. The evidence method notes and the glossary hold these terms to one fixed sense.

The desk does not publish guidance on making produced activity harder to collect or harder to read. Produced volume is a normal, openly sold category of market activity, and the interest here is in reading it accurately rather than condemning it or helping anyone hide it. That standing rule is why some otherwise natural sections stop early.

Questions this desk is asked

Why write the question before pulling the data?

Because a question written after the data is a story rather than a test. Once you have looked at a chart you already know which window, which wallets and which threshold make the pattern look strongest, and every later choice quietly bends towards that picture. Writing the question first fixes what would count as a negative answer, which is the only thing that makes the positive answer worth anything.

What makes an observation window arbitrary?

A window is arbitrary when it was chosen after seeing the data and cannot be justified by an event outside the data. Windows anchored to a pool creation slot, a migration, a listing or a fixed calendar block are defensible. Windows that begin exactly where a burst begins and end exactly where it ends are not, because they encode the conclusion in the sample and cannot be tested by anyone else.

Why store raw fields instead of computed ratios?

A ratio is a summary with its inputs thrown away. If you store a buy to sell ratio and later discover the parser mislabelled one instruction type, the ratio cannot be corrected, only discarded. Storing the pre and post token balances that produced it means every later dispute is a recomputation rather than a fresh pull, which is usually impossible once history has been pruned.

How do routed trades inflate a transaction count?

An aggregator can split one user action across several pools, so a single signature contains several swap instructions. Counting instructions gives one number, counting signatures gives another, and counting fee payers gives a third. None is wrong, but a report that mixes them will describe activity that no user performed. Fold legs back to the user action, then say in the log which unit you counted.

What should be done about missing history?

Record it. RPC providers paginate signature queries, prune old history and rate limit heavy pulls, so most windows have holes. The honest response is a gap entry naming the slot range, the reason and the provider, not an interpolated estimate. A reading built on an incomplete window can still be useful if the incompleteness is visible; it becomes misleading the moment the gap is smoothed away.

What is a chain-of-custody note in this context?

A short record of who pulled what, from where, when, and with which rule versions. It names the endpoint, the slot range, the parser version, the deduplication rule and the operator. It is not a legal instrument. Its only job is to let a second analyst repeat the pull, get the same set, and then disagree about the interpretation rather than about the data.

Does a well collected dataset prove manipulation?

No. Collection produces evidence, not a verdict. A clean, reproducible pull can support a reading that produced flow is present, but produced flow is an openly sold service and its presence is a description of activity, not an accusation. Intent lives off chain, and every inference drawn from the data should carry a confidence band and a statement of what would overturn it.

Filed in Evidence by The Volume Forensics Desk. Patterns described here come from protocol design and public transaction data; every figure in an example is invented, labelled and describes no real pair. The evidence standard the desk works to is set out in stating confidence honestly, and the terms used are defined in the glossary.