Analytical reporting · Lesson 3 of 6
Visualizing flows and graphs
8 min read
Most readers of an on-chain report look at the pictures first and the text second, and some never read the text at all. A good flow diagram lets a prosecutor, a compliance officer or an editor grasp in ten seconds where the money went; a bad one plants a conclusion the evidence does not support. This lesson covers the four visuals analysts use most, how to build them from query results, and how to keep them honest and readable by everyone.
Choose the visual by the question
Start from the question the reader needs answered, not from the tool you have open.
| Reader's question | Best visual | What it hides |
|---|---|---|
| How much went where? | Sankey diagram | Timing, individual transactions |
| How are these addresses connected, and by which path? | Flow graph | Amounts, unless labeled |
| When did things happen, and in what order? | Timeline | Network structure |
| Which addresses belong to which entity? | Cluster map | Flow direction and timing |
| How did a balance or volume change over time? | Line or bar chart | Counterparties |
Every visual simplifies, and each hides something. A report that needs to show amount, path and time usually needs two or three figures, each doing one job, rather than one figure that tries to do everything.
Sankey diagrams
A Sankey diagram draws flows as bands whose width is proportional to the value moved. It is named after Matthew Sankey, who used one in 1898 to show the energy efficiency of a steam engine, and it is the clearest way to show how a sum was split.
Worked example. An exploiter address holds 941.2 ETH after swapping its loot. A Sankey shows three bands leaving it: 600 ETH to a cross-chain swap service, 300 ETH to a bridge, and 41.2 ETH that stayed put. The bands' widths are in the ratio 600 : 300 : 41.2, so the reader sees at once that almost two thirds went one way.
Rules that keep a Sankey honest:
- Conserve value. What enters a node should equal what leaves it plus what stays. Show fees, unspent balances and untraced amounts as explicit bands ("fees 0.002 BTC", "unmoved 41.2 ETH", "not traced"), never let them silently disappear.
- One unit per diagram. Do not mix ETH and BTC bands. Either draw one Sankey per asset, or convert to a single currency at the time of each transfer and state the price source.
- Order the columns by hop or by time, left to right, and say which.
- Avoid cycles. Sankey layouts assume flow in one direction. Round-tripping (see Graph metrics and patterns) belongs in a flow graph.
The data behind a Sankey is an edge list: source, target, value. A query over a table of traced transfers produces it directly:
-- Edge list for a Sankey: value moved between labeled entities
SELECT
COALESCE(ls.entity, t.from_address) AS source,
COALESCE(lt.entity, t.to_address) AS target,
SUM(t.amount_wei) / 1e18 AS eth_moved, -- precision: see note
COUNT(*) AS transfers
FROM traced_transfers t
LEFT JOIN labels ls ON ls.address = t.from_address
LEFT JOIN labels lt ON lt.address = t.to_address
GROUP BY 1, 2
ORDER BY eth_moved DESC;
The two left joins replace addresses with entity names where a label exists and keep the raw address otherwise. Falling back to the address, rather than to a single "Unlabeled" bucket, matters: one "Unlabeled" node would merge unrelated addresses and draw flows between them that never happened. The joins assume one label per address; if the label table can hold several, keep one first, as shown in the lesson Joins, window functions and CTEs for flows, or the sums fan out. Two portability notes: positional GROUP BY 1, 2 works in most engines but not all, and dividing by 1e18 produces a floating-point number in many engines, so for exact figures cast to a high-precision decimal type first (see SQL foundations for blockchain tables).
Flow graphs
A flow graph draws addresses or entities as boxes and transfers as arrows. It is the native picture of tracing work (see Transaction graphs: nodes, edges and direction).
- Use a layered, left-to-right layout for traces, with each column a hop or a time step. Readers then follow the money like text.
- Use force-directed layouts only for exploration. In those layouts, position is an artifact of the algorithm: two nodes drawn close together look related even when they are not. Never put such a layout in a report without explaining it.
- Label edges with amount, date and a short transaction reference, and keep the full hash in the appendix.
- Distinguish observed from inferred. Draw transfers that are facts as solid arrows and links that are inferences (an amount-time bridge match, a change-output call) as dashed arrows, with the likelihood term next to them. This carries the fact–inference split from the lesson Confidence, uncertainty and language into the picture.
- Show where tracing stopped. A short stub labeled "not traced further" or "custodial service" tells the reader the boundary is a choice, not the end of the money.
- Keep it small. Above about 30 to 50 nodes a graph stops being readable. Collapse peel chains into one box ("peel chain, 9 hops") and clusters into one node, and put the detail in an appendix.
Open tools such as Graphviz (layered layouts), Gephi and Cytoscape (network exploration) and charting libraries such as d3 are common choices; whatever you use, export the underlying edge list with the figure so it can be checked.
Timelines
A timeline answers "when" and "in what order", which often matters more to legal and operational readers than the path itself: how fast did funds reach an exchange, was there time to freeze them?
- Use UTC throughout and show block heights alongside times.
- For cross-chain cases, use one swimlane per chain, so a bridge deposit on one lane and its release on another sit side by side.
- Gaps carry meaning: a dormant period of weeks shows up as empty space. If you compress the axis to save room, mark the break clearly.
Cluster maps
A cluster map shows entity resolution: which addresses were grouped together and why. Draw each cluster as a container and the addresses (or address counts) inside it, and draw the reason for each link, such as common inputs or shared deposit address, as a distinct line style. If the cluster size is shown by bubble area, say whether it encodes address count or balance. Warn the reader when a cluster is suspiciously large, because superclusters are a known failure mode (see Evaluating cluster quality).
Avoiding misleading layouts
Visuals mislead more often through layout choices than through wrong data. Check every figure against this list:
- Truncated or inconsistent axes: a bar chart whose axis starts at 900 ETH makes 950 look double 925. Use the same scale across charts meant to be compared.
- Area versus length: if bubble radius encodes value, doubling the radius quadruples the area and exaggerates the difference. Scale area, not radius.
- Unlabeled log scales: useful for wide ranges, misleading if the reader assumes linear.
- Loaded color: red for an entity that is only suspected implies a verdict. Use neutral colors and reserve warning colors for established facts, such as a confirmed exploit contract.
- Selective omission: showing only the paths that reach the suspect while dropping the larger flows that went elsewhere.
- False precision: "1,912,400.000000 USDC" in a figure suggests a certainty about attribution that the amount does not carry; round in figures, keep exact values in the appendix.
Accessibility
Reports are read on phones, printed in grayscale and read by people with color-vision deficiency, which affects roughly 1 in 12 men and 1 in 200 women. The Web Content Accessibility Guidelines (WCAG 2.1 and 2.2) give useful targets even for documents that are not web pages:
- Text contrast of at least 4.5:1 against its background (3:1 for large text).
- Contrast of at least 3:1 for meaningful graphical elements such as lines and bands.
- Never use color alone to carry meaning: pair it with labels, patterns or line styles (solid for observed, dashed for inferred works in grayscale too).
Give every figure alt text or a caption that states the takeaway ("two thirds of the funds went to the cross-chain swap"), not just a description ("a Sankey diagram"), and include the underlying table in the appendix so readers using screen readers, and reviewers, get the same information.
Exam focus: matching the visual to the reader's question (Sankey for amounts, flow graph for paths, timeline for order, cluster map for entity resolution); Sankey rules (conservation, explicit fees and untraced amounts, one unit per diagram, no cycles); building an edge list in SQL without merging unlabeled addresses; layered versus force-directed layouts; solid arrows for facts and dashed arrows for inferences; showing where tracing stopped; common misleading choices (truncated axes, area versus radius, loaded color, omission); WCAG contrast targets of 4.5:1 for text and 3:1 for graphics, and never relying on color alone.