⚠️ Experimental. Like the rest of Graph, the flow view is outside the 1.0 stability guarantee. This release lays nodes out from hints in the data; automatic in-lane layout, aggregation and collapsible groups come next.
The flow view draws a trace: value moving between entities, left to right through ordered lanes — networks, stages, jurisdictions. Ties are directed, may repeat between the same pair (a swap there and back, a deposit and a withdrawal), and carry value (width), category (color), certainty (dash) and a label. It is the view for money trails, supply chains and address investigations.
The demo below follows funds as they move: income from a validator is swapped, bridged and moved through five networks, then spent on a token crowdfunding — and the trace goes on to show where the sale money went. Read it left to right: lanes are networks, line color is the asset, width its USD value, a dashed line an amount derived rather than read from transactions. Click the Crowdfunding node to fold the sale away and focus on the route that led to it (click again to bring it back); the legend's address poisoning item reveals a look-alike address that tried to pass as the team's.
Select a node or a tie: the chart reports it through onSelect, and the page fills the details panel — placed inside the card with the details option: beside the drawing on a wide screen, below it on a narrow one. The library draws, your page explains. The Crowdfunding node's open/close is page code in the same onSelect handler, switching a setFilter (collapsible groups built into the library come in the next release); the decoy starts hidden with hiddenLinkTypes: ['noise'].
Data
The same { nodes, links } contract as every Graph view. Hints on the nodes place them; any extra field passes through to onSelect and the tooltips untouched.
new RareCharts.Graph('#chart', {
view: 'flow',
lanes: [{ id: 'osmosis', label: 'Osmosis' }, { id: 'ethereum', label: 'Ethereum', weight: 3 }],
laneBy: 'net', // node field naming its lane
nodeGroups: { tracked: { color: '#2c5d8f', label: 'tracked wallets' } },
nodeShapes: { wallet: 'circle', contract: 'square', exchange: 'diamond', crowd: 'stack' },
linkColorBy: 'asset',
linkTypes: { ETH: { color: '#3d4a5c', label: 'ETH' } },
linkWidth: { by: 'value', scale: 'sqrt', min: 1.6, max: 22 },
linkDash: link => link.basis === 'derived',
hulls: [{ id: 'owner', label: 'one key on five networks', members: n => n.cluster }],
hiddenLinkTypes: ['noise'], // off until turned on in the legend
details: '#details', // your panel, placed beside or below the drawing
onSelect: ({ node, link }) => showDetails(node ?? link),
}).setData({
nodes: [
{ id: 'osmo', label: 'Owner wallet', sub: 'osmo1uvkv…w7zs', group: 'tracked', kind: 'wallet', net: 'osmosis', row: 0 },
],
links: [
{ from: 'osmo', to: 'swap-dex', asset: 'ATOM', value: 530, label: '61.38 ATOM', start: '2023-09' },
],
});
Placing nodes
lane(or the field named bylaneBy) puts a node in a lane. Lanes split the width byweight, in the order given; a lane only the data mentions is appended.rowis the vertical slot:0is the main line,-1,-2above,1,2below. A node without a row takes the next free slot of its cell.colsplits a wide lane into sub-columns (0,1, …).x/yoverride both, as fractions0..1of the lane width and of the drawing height.
Ties
source/target(orfrom/to), plus any fields you need. Several ties between one pair fan out;bendadjusts a curve by hand.- Width comes from
linkWidth—valuethrough a square-root scale by default; a tie without a value gets the minimum width. - Color comes from
linkColorBy(a field or a function) resolved againstlinkTypes; dash from the type or fromlinkDash(link). - Time:
start/end(years,YYYY-MMor ISO dates).setTimeWindow(from, to)dims ties outside the window — and fades nodes whose ties are all outside — or hides them withtimeWindowMode: 'hide'.
Options
Flow-specific options; the common Graph options (height, details, fullscreen, linkTypes, tooltips…) are on the Graph page.
| Option | Type | Default | Description |
|---|---|---|---|
view | string | — | 'flow' turns the flow view on |
lanes | array | [] | [{ id, label, weight? }] in left-to-right order; weight sets a lane's share of the width |
laneBy | string | function | 'lane' | Node field (or function) naming its lane |
nodeGroups | object | — | { group: { color, label } } — node color and legend entry |
nodeShapes / shapeBy | object / string | function | {} / 'kind' | Shape per node kind: 'circle', 'square', 'diamond', 'stack', or an SVG path |
linkColorBy | string | function | 'type' | Tie field (or function) whose value is looked up in linkTypes |
linkWidth | object | { by: 'value', scale: 'sqrt', min: 1.6, max: 22 } | Tie width from a value field; scale: 'linear' also available |
linkDash | function | — | link => boolean — dashed tie (e.g. a derived amount); a type's own dash wins |
linkLabels | boolean | true | Tie labels; also setLinkLabels() |
hulls | array | [] | [{ id, label, members, color? }] — a soft band through a group's nodes; members is a list of ids or node => boolean |
hiddenLinkTypes | array | [] | Tie categories hidden at start; the legend shows them dimmed and turns them on |
timeWindowMode | string | 'dim' | What setTimeWindow does to ties outside the window: 'dim' or 'hide' |
onSelect | function | — | ({ node, link, event }) => void on selection; without it, a clicked tie pins its tooltip |
minWidth | number | 0 | Narrower drawings scroll sideways instead of crushing the lanes; a side details panel needs this much room next to it, or it moves below |
nodeRadius | number | 18 | Node radius in the flow view |
Methods
graph.setFilter(item => !item.noise); // nodes and ties; a tie hides with either end
graph.setTimeWindow(null, '2024-01'); // open start, through January 2024
graph.select('osmo'); // or select({ link: id }); clearSelection()
graph.setLinkLabels(false);
graph.setHulls([]);
Interaction
Select — click a node or a tie: its neighbourhood stays, the rest fades, and onSelect({ node, link, event }) fires; click the background or press Escape to clear. Without onSelect, clicking a tie pins its tooltip instead.
Keyboard — nodes are in the Tab order lane by lane; Enter or Space selects; → follows an outgoing tie, ← an incoming one, ↑ / ↓ move within a lane.
Legend — node groups and tie categories; click a category to hide or show its ties. Categories in hiddenLinkTypes start hidden. A node whose ties are all hidden is hidden with them.
Details — with details, the selected node or tie is explained in a panel inside the card: beside the drawing on a wide card, below it on a narrow one (see the Graph options).
Full screen — ⛶ in the footer opens the trace on the whole screen; Esc or ✕ closes it.
Narrow screens — set minWidth and the chart scrolls sideways instead of crushing the lanes; a details panel moves below the drawing.