# Agent guide to the Cardano exchange tracer data

> **Network:** Cardano mainnet
>
> **Study:** The Red (or Blue) Pill Study
>
> **Purpose:** answer user questions by querying and reconstructing the public
> on-chain tracer data.

This guide is an operating manual for an agent incorporating the study's
on-chain data into a user's own query. The agent should retrieve the relevant
Cardano transactions, construct only the graph needed for the question, and
return auditable evidence with clear limits.

The study follows unique Cardano native assets after participants deposit them
to exchange addresses. A non-fungible asset has an exact transaction path.
ADA value paths are weaker evidence because ADA commingles.

## Agent operating contract

When a user asks about these tracers:

1. Restate the question as an on-chain measurement.
2. Identify the minimum tracer assets, transactions, addresses, and time range
   needed to answer it.
3. Query current chain data. Do not answer a current-state question from a
   remembered snapshot.
4. Preserve transaction hashes, output indexes, block positions, and exact
   asset IDs while working.
5. Separate observations from calculations and interpretations.
6. Treat an NFT movement as exact for that asset.
7. Treat wallet clustering, exchange names, and ADA value paths according to
   their stated evidence limits.
8. Give the result, the denominator, the query tip or time, and enough
   transaction evidence for independent checking.
9. Say when the available chain data cannot answer the user's question.

Never turn contact with an address into a claim of custody, ownership, or
personal identity. Never turn a self-reported exchange name into verified
exchange attribution.

## Translate a user question into a query

Route the question before fetching data:

| User wants to know | Required on-chain work | Report |
|---|---|---|
| Where is tracer X now? | Resolve the asset name, then query its current UTxO | Current transaction, output, address cluster, and query time |
| Where has tracer X been? | Fetch its full asset history and resolve every asset-bearing output | Ordered holder path with carrying transactions |
| How many tracers reached exchanges? | Reconstruct valid tagged deposits, then inspect each current terminus | Numerator, total eligible tracers, status buckets, and snapshot time |
| Which exchange does a cluster indicate? | Group by terminus and count distinct participant keys per reported name | Full vote split, threshold, resolved name or unresolved result |
| Did several participants converge? | Compare pre-deposit participant keys and downstream terminus keys | Distinct participant count, tracer count, and shared node |
| Is a Coinbase or Kraken label supported? | Filter claims by name, cluster them by terminus, and count distinct participant keys | Supporting tracers, supporting participant keys, conflicts, and threshold result |
| What is a node's degree? | Build the requested directed subgraph and define edge weighting | In-degree, out-degree, weighting rule, node-key rule, and time window |
| Where did the associated ADA go? | Perform a separate bounded dominant-value walk | Indicative path, hop cap, excluded self-change, and uncertainty |
| Did the result change? | Run the same measurement at both stated snapshots | Added, removed, and changed assets or clusters, with both denominators |

If the question lacks a time range, use current chain state and state the query
time. If it lacks a graph definition, use the wallet-cluster and edge rules
below and disclose them. Ask for clarification only when different reasonable
definitions would materially change the answer.

## Query execution loop

Use this loop for every request:

```text
user question
  -> measurement and denominator
  -> smallest asset or address seed set
  -> paginated Koios retrieval
  -> exact NFT path reconstruction
  -> optional wallet clustering or value overlay
  -> requested statistic
  -> transaction-backed answer with limits
```

Cache immutable transaction details by transaction hash. Refresh current UTxOs
and the chain tip for current-state questions. When several compatible Koios
endpoints are available, alternate requests between them, keep pagination
stable within each request, and cool down an endpoint after a quota response.

## Canonical identifiers

- Tracer policy ID:
  `d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119`
- Policy key hash:
  `55bf845d5be91cf210e50511fc34ff35aad645f92290c13c5c3b4186`
- Native-script expiry: mainnet slot `223391762`
- Deposit metadata: CIP-20 transaction message, label `674`
- Historical study-seed metadata: label `1985`
- Study name in metadata: `The Red (or Blue) Pill Study`
- Study site in metadata: `tracer.adagenesistransparency.com`
- Exchange-name threshold used by the map: `2` distinct external participant
  wallets supporting the same name in one cluster
- Policy explorer:
  `https://cardanoscan.io/tokenPolicy/d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119`

The policy ID is the asset identity boundary. Do not select assets by a
`TRACER` name prefix alone.

## Querying with Koios

The examples use the public Cardano mainnet Koios endpoint:

`https://api.koios.rest/api/v1`

Public providers enforce rate and payload limits. Paginate every list, cache
immutable transaction responses, keep transaction batches small, and retry
transient failures. If using several compatible endpoints, rotate requests
between them and temporarily cool down an endpoint after a quota response.

### 1. List every asset under the policy

Paginate in blocks of 1,000:

```bash
curl --get 'https://api.koios.rest/api/v1/policy_asset_list' \
  --data-urlencode '_asset_policy=d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119' \
  --data-urlencode 'select=asset_name,fingerprint,total_supply' \
  --data-urlencode 'offset=0' \
  --data-urlencode 'limit=1000'
```

Continue with offsets `1000`, `2000`, and so on until a page contains fewer
than 1,000 rows.

`asset_name` is hexadecimal. Decode it as UTF-8 for a human-readable tracer
name. Preserve the hexadecimal form for API queries. Confirm that supply is
`1` before treating an asset as non-fungible.

The full asset identifier is:

```text
<policy_id><asset_name_hex>
```

### 2. Find a tracer's current unspent output

Replace `<ASSET_NAME_HEX>` with the hexadecimal asset name:

```bash
curl 'https://api.koios.rest/api/v1/asset_utxos' \
  -H 'content-type: application/json' \
  --data '{
    "_asset_list": [
      [
        "d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119",
        "<ASSET_NAME_HEX>"
      ]
    ],
    "_extended": false
  }'
```

Record the transaction hash, output index, payment address, and stake address.
Use the transaction hash plus output index as the current-state key. An
address alone is insufficient because a tracer can leave an address and later
return to it.

### 3. Fetch the tracer's complete transaction history

```bash
curl --get 'https://api.koios.rest/api/v1/asset_txs' \
  --data-urlencode '_asset_policy=d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119' \
  --data-urlencode '_asset_name=<ASSET_NAME_HEX>' \
  --data-urlencode '_history=true' \
  --data-urlencode 'offset=0' \
  --data-urlencode 'limit=1000'
```

Paginate until a page contains fewer than 1,000 rows. Deduplicate transaction
hashes before resolving them.

### 4. Resolve transaction inputs, outputs, assets, and metadata

```bash
curl 'https://api.koios.rest/api/v1/tx_info' \
  -H 'content-type: application/json' \
  --data '{
    "_tx_hashes": ["<TX_HASH>"],
    "_inputs": true,
    "_metadata": true,
    "_assets": true
  }'
```

Keep batches at 50 transaction hashes or fewer unless the selected provider
documents a higher safe limit.

For every transaction:

1. Inspect each output's asset list.
2. Select the output containing quantity `1` of the exact policy ID and asset
   name.
3. Record its payment address, stake address, output index, block height,
   transaction index, and timestamp.
4. Order the asset-bearing outputs by block height and transaction position.
5. Deduplicate consecutive outputs assigned to the same wallet-cluster key.

That ordered sequence is the NFT's exact holder path. If the final
asset-bearing output is unspent, it is the current terminus. If no unspent
output exists, distinguish a burn from incomplete provider history before
classifying it.

## Deposit metadata convention

A participant deposit normally carries CIP-20 label `674` with a `msg` array:

```json
[
  "Deposited to:",
  "<exchange name>",
  "The Red (or Blue) Pill Study",
  "tracer.adagenesistransparency.com",
  "<optional participant message>"
]
```

The exchange name is `msg[1]`. It is the depositor's claim.

Apply the memo only when all of these conditions hold:

1. The transaction has label `674`.
2. The message identifies this study.
3. Output `0` contains quantity `1` of an asset under the tracer policy.
4. That output moves the tracer to a wallet-cluster key distinct from the
   tracer's preceding holder.

The memo applies only to the tracer in output `0`. Tracers returned as change
in later outputs do not inherit the exchange name.

Other applications also use label `674`. A matching label without a
study-policy tracer in output `0` is unrelated metadata.

Label `1985` appears on early study-seed transactions. Do not treat arbitrary
label-1985 metadata as a participant exchange report.

### The tagged deposit is the exchange-path boundary

For a label-backed exchange path, begin with the qualifying label-674
transaction and follow the tracer forward from its output `0`.

Disregard earlier NFT movements when calculating the exchange path,
exchange-cluster convergence, downstream node degree, or tracer counts for
that deposit. Before the qualifying message, the participant may have
purchased, received, reorganized, or moved the NFT among wallets they control.
Those transactions establish the tracer's holder provenance, but they do not
establish exchange contact.

The wallet-cluster key immediately before the deposit is still used as the
participant unit for voting. Do not count every earlier wallet on the tracer's
path as another participant.

### Direct deposits without the transaction builder

Some participants may send a tracer directly to an exchange without using the
study's transaction builder. Such a transaction may have no label `674`, an
incomplete message, or a different output arrangement. Absence of the study
message is not evidence that the destination is unrelated to an exchange.

Handle an untagged tracer as follows:

1. Preserve its complete exact NFT path.
2. Do not assign it a self-reported exchange name.
3. Do not count it as a participant vote for any exchange.
4. If it reaches a wallet cluster already identified by independent tracer
   votes or cited evidence, count it as an additional tracer contacting that
   cluster.
5. Report its attribution as convergence with an identified cluster, not as a
   labelled deposit.
6. If it reaches an unknown cluster, retain it as an unattributed candidate
   and test the topology heuristics below.

This keeps untagged direct deposits visible without allowing an inferred name
to create or strengthen its own label vote.

### Address-form and topology heuristics

Byron-era mainnet addresses commonly begin with `DdzFF` or `Ae2`. These
base58 address forms have no stake credential. A Byron address that terminates
many independent tracer paths can be a useful exchange-infrastructure
candidate, especially when it also has:

- high distinct-source in-degree;
- repeated NFT or token fan-in;
- regular batching or consolidation transactions;
- high transaction throughput;
- onward sweeps into a smaller set of recurring wallets;
- convergence from deposits carrying independently corroborated exchange
  names.

The prefix alone carries no exchange attribution. Byron addresses also belong
to early personal wallets, founding wallets, and other non-exchange users.
Require behavioral convergence or direct evidence before treating one as
exchange infrastructure. The same caution applies to enterprise addresses and
other addresses without stake credentials.

## Wallet-cluster keys

Use one deterministic key for every holder:

- `s:<stake_address>` when a Shelley payment address has a stake credential.
- `a:<payment_address>` when no stake credential is present, including
  enterprise and Byron addresses.

Grouping payment addresses by a shared stake credential is an on-chain wallet
heuristic. It does not prove corporate identity, custody, or beneficial
ownership.

For each tracer, transform the ordered holder path into:

```text
node_0 -> node_1 -> node_2 -> ... -> current_terminus
```

Each edge should retain:

- the transaction hash;
- block height and timestamp;
- policy ID and asset name;
- source and destination cluster keys;
- output index;
- whether the edge is the metadata-tagged deposit.

The NFT edge is exact: that specific asset moved in that transaction.

## Reconstructing exchange convergence clusters

Start at each valid tagged deposit and follow that tracer forward to its
current terminus. Then group tracers that reach the same wallet-cluster key.

For every terminus cluster, calculate:

- number of distinct tracer assets;
- number of distinct pre-deposit participant cluster keys;
- number of distinct deposit transactions;
- count of tracers for each reported exchange name;
- count of distinct participant cluster keys for each reported exchange name;
- first and last observed deposit time;
- exact NFT edges entering and leaving the cluster.

Participant count is the naming vote. Tracer count is volume. One participant
sending several tracers still contributes one vote to a given exchange name.

Resolve a public name only when:

1. one exchange name has a unique lead by distinct participant count; and
2. that name has at least `2` distinct external participant wallets.

If the top participant counts tie, leave the cluster unresolved. Preserve the
complete name split so minority or mistaken reports remain visible.

Example evidence summary:

```json
{
  "tracers": 11,
  "participants": 5,
  "claims": [
    {
      "exchange": "Kraken",
      "tracers": 10,
      "participants": 5,
      "corroborated": true
    },
    {
      "exchange": "Coinbase",
      "tracers": 1,
      "participants": 1,
      "corroborated": false
    }
  ],
  "resolvedExchange": "Kraken",
  "conflicted": true
}
```

The current on-chain Kraken cluster contains this pattern. The Coinbase report
is retained as a conflicting claim and does not determine the cluster name.

## Study operations and reproducibility

The asset path itself is public and independently reproducible. Classification
of a wallet as a genuine participant, operator, or demo source can include
off-chain provenance and is not fully derivable from transaction shape alone.

For a chain-only reconstruction:

- publish every raw label claim;
- count distinct pre-deposit wallet-cluster keys;
- do not describe those keys as independent people;
- report whether any exclusion list or off-chain provenance was applied;
- do not claim exact parity with the site's participant-voting statistics
  unless the same exclusions have been independently documented.

This distinction does not weaken the exact NFT path. It limits only the
interpretation of who supplied a label vote.

## Node degree

For a directed graph:

- In-degree is the number of distinct upstream nodes with edges into a node.
- Out-degree is the number of distinct downstream nodes receiving edges from
  a node.
- NFT-weighted degree counts distinct tracer assets on those edges.
- Transaction-weighted degree counts distinct carrying transactions.
- Participant-weighted in-degree counts distinct pre-deposit participant
  cluster keys.
- Temporal degree measures the same quantity within a stated block or date
  window.

A high in-degree is a fan-in or aggregation signal. A high out-degree is a
fan-out or distribution signal. Neither proves that a wallet is an exchange.

Always state:

- whether the graph is directed;
- whether parallel NFT movements are separate edges or weights;
- the time window;
- the exact node-key rule;
- which evidence types were included.

## Exchange-cluster shape

An exchange-shaped cluster often contains:

- many low-activity deposit addresses;
- repeated convergence into fewer aggregation wallets;
- one or more high-throughput hot or consolidation wallets;
- recurring batching transactions;
- tracer assets that enter through different participant deposits and later
  share a terminus.

Useful measures include:

- distinct-source convergence;
- weakly connected components;
- strongly connected components for recycling or churn;
- edge multiplicity by NFT or transaction;
- temporal in-degree;
- Jaccard overlap between the tracer sets observed at two nodes.

Use shape as corroboration, not as identity proof.

## Optional ADA value sweep

The NFT path answers where the tracer asset moved. To examine the associated
ADA flow, query transactions that spend outputs from the deposit address after
the tagged deposit.

For each candidate spending transaction:

1. group outputs by destination wallet-cluster key;
2. exclude outputs returning to the source cluster as self-change;
3. sum lovelace by remaining destination;
4. record the largest destination as the dominant forward output;
5. repeat for a bounded number of hops;
6. stop at a previously visited node, a clear hub, or the hop cap.

Mark every such edge `value-indicative`. ADA commingles, so a dominant output
is an indicator of flow, not a cryptographic continuation of the deposited
value.

Never combine exact NFT edges and indicative ADA edges into one unlabeled
centrality or path calculation.

## Minimal independent reconstruction

1. List and paginate every asset under the policy.
2. Confirm each tracer has supply `1`.
3. Fetch and paginate each asset's complete transaction history.
4. Resolve referenced transactions in small `tx_info` batches.
5. Select the exact asset-bearing output from each transaction.
6. Sort those outputs by block and transaction position.
7. Convert addresses to deterministic `s:` or `a:` cluster keys.
8. Parse label `674` only when output `0` carries the tracer and moves it to a
   distinct cluster key.
9. Follow the NFT from that deposit output to its terminus.
10. Group tracers by terminus.
11. Count tracers and distinct pre-deposit wallet keys separately for every
    reported exchange name.
12. Resolve only a unique threshold-clearing participant-vote leader.
13. Preserve dissenting labels and unresolved ties.
14. Keep optional ADA value edges separate and mark them indicative.

## Agent query recipes

### Answer: "Where is this tracer now?"

1. Accept either the full asset ID, policy ID plus hexadecimal asset name, or a
   decoded tracer name.
2. Reject an asset outside the canonical policy.
3. Query `asset_utxos`.
4. If one unspent output exists, return its transaction hash, output index,
   address cluster, and query time.
5. If none exists, inspect full history before saying the asset was burned.
6. If several appear, report inconsistent provider data and do not choose one.

### Answer: "How many participants support this exchange label?"

1. Reconstruct every valid tagged deposit carrying that normalized label.
2. Record the wallet-cluster key holding the tracer immediately before deposit.
3. Follow each deposited tracer to its current terminus.
4. Group by terminus.
5. Within each terminus, count unique pre-deposit keys, not deposit
   transactions.
6. Show tracer count and participant-key count separately.
7. Show other names reported for the same terminus.
8. Apply the two-participant threshold only after any documented study
   exclusions.

Normalize case and surrounding whitespace for counting, but retain the exact
on-chain spelling in the evidence.

### Answer: "Are these tracers in the same exchange cluster?"

1. Reconstruct the exact NFT path for each requested tracer.
2. Compare current terminus keys first.
3. If current termini differ, compare earlier downstream nodes only when the
   user asks about historical convergence.
4. Return the shared key, each carrying transaction, and whether the
   convergence is current or historical.
5. Describe the result as shared on-chain contact. An exchange identity still
   depends on the label-voting evidence.

### Answer: "What changed since an earlier run?"

Use identical policy, node-key, deposit-validation, participant-counting, and
status rules for both snapshots. Compare by stable identifiers:

- tracer asset ID for individual paths;
- transaction hash plus output index for positions;
- wallet-cluster key for nodes;
- source key, destination key, transaction hash, and asset ID for edges.

Report:

- newly discovered and no-longer-observed tracers;
- tracers whose current UTxO changed;
- cluster membership changes;
- participant and tracer count changes;
- label-resolution changes;
- any methodology or provider-coverage change that prevents a clean delta.

Do not infer historical state from a current UTxO query. Use the prior
snapshot or a block-bounded reconstruction.

## Answer contract

Lead with the direct answer. Then provide a compact evidence record:

```json
{
  "answer": "<direct result>",
  "asOf": {
    "queriedAt": "<ISO-8601 time>",
    "blockTip": "<Cardano block hash or height>",
    "provider": "<Koios endpoint>"
  },
  "scope": {
    "policyId": "d8d5539ee11f21a6748735aeb69d3ed935bb14570f57709279031119",
    "assetsExamined": 0,
    "eligibleAssets": 0,
    "timeRange": "<range or current state>"
  },
  "measurement": {
    "nodeKey": "stake credential when present, otherwise payment address",
    "edgeType": "exact-nft",
    "participantUnit": "distinct pre-deposit wallet-cluster key",
    "threshold": 2
  },
  "result": {},
  "evidence": [
    {
      "txHash": "<transaction hash>",
      "outputIndex": 0,
      "assetId": "<policy ID plus asset name>",
      "observation": "<what this transaction proves>"
    }
  ],
  "limits": ["<claim the chain data cannot establish>"]
}
```

Adapt the fields to the question rather than returning empty sections. For a
human-facing answer, render the same information as prose or a table and link
transaction hashes to a public Cardano explorer.

When evidence conflicts, preserve the conflict in `result` and explain which
rule determined the answer. When the threshold is not met, return
`unresolved`; do not select the most familiar name.

## Interpretation limits

- A tracer proves that the asset contacted an address. It does not prove
  custody, beneficial ownership, or the identity of a person.
- A label-674 exchange name is a depositor's claim.
- Several deposits from one wallet are one wallet-level source, not several
  independent votes.
- Several wallet keys are not necessarily several people.
- A shared stake credential is an on-chain wallet cluster, not a corporate
  identity.
- Dominant ADA output is an indicator, not proof of value origin or
  destination.
- Hub shape can also occur in protocols, payment services, custodians, and
  other high-volume systems.
- Current position and all-time passage are different questions.
- Absence from a reconstruction can mean incomplete history, pagination
  failure, provider lag, or insufficient coverage.

When publishing derived results, include the policy ID, query date, Cardano
block tip, Koios endpoint or mirror, pagination rules, node-key rule, edge
evidence types, label threshold, and any off-chain exclusions.

## Appendix: reconstructing exchange graph topology

This appendix describes a bounded topology reconstruction around tagged
deposits, untagged tracer paths, and candidate exchange infrastructure. It is
designed for answering a user's specific query, not for absorbing every
transaction on the chain into one cluster.

### 1. Keep a transaction graph as the canonical model

Represent transactions and wallet clusters as separate node types:

```text
wallet cluster -> spending transaction -> receiving wallet cluster
```

For each input, retain:

- the spent transaction hash and output index;
- the spending address and wallet-cluster key;
- lovelace and native assets consumed;
- whether the exact tracer asset was present.

For each output, retain:

- the new transaction hash and output index;
- the receiving address and wallet-cluster key;
- lovelace and native assets created;
- whether the exact tracer asset was present.

This bipartite form prevents a common error. A transaction with several inputs
and outputs does not prove that every input funded every output. Project it
into a wallet-to-wallet graph only after assigning an evidence type.

### 2. Fetch transactions around a candidate node

For a payment address, query its transaction hashes:

```bash
curl 'https://api.koios.rest/api/v1/address_txs?limit=1000&offset=0' \
  -H 'content-type: application/json' \
  --data '{
    "_addresses": ["<PAYMENT_ADDRESS>"],
    "_after_block_height": 0
  }'
```

Paginate with offsets `1000`, `2000`, and so on. Use
`_after_block_height` as a lower bound when the question has a block or date
boundary. Resolve the returned hashes with `tx_info` in small batches. For a
stake-key cluster, retrieve every relevant payment address before combining
their statistics under the shared `s:` key.

Bound each expansion by a stated block range, date range, hop count, and
transaction cap. A high-volume hub can otherwise turn a focused query into an
unbounded chain crawl.

### 3. Build evidence-typed wallet edges

Use separate edge classes:

- `exact-nft`: an input and output carry the same unique tracer asset;
- `tx-cooccurrence`: the wallets occur on opposite sides of one transaction,
  but the value assignment is unknown;
- `value-indicative`: a bounded dominant-value rule selects the destination;
- `self-change`: an output returns to a wallet cluster represented among the
  inputs;
- `label-backed-deposit`: the exact NFT edge also satisfies the study's
  label-674 and output-0 convention.

Never silently convert `tx-cooccurrence` into an exact value path. Compute NFT
topology and indicative value topology separately, then show where they
overlap.

### 4. Calculate node statistics

For each wallet-cluster node, calculate at least:

| Measure | Definition | Useful signal |
|---|---|---|
| Distinct in-degree | Unique external wallet clusters sending into the node | Source convergence |
| Distinct out-degree | Unique external wallet clusters receiving from the node | Distribution or fan-out |
| Input transaction count | Transactions with an input from the node | Spending activity |
| Output transaction count | Transactions creating an output at the node | Receiving activity |
| Tracer in-degree | Distinct tracer assets arriving | NFT aggregation |
| Tracer out-degree | Distinct tracer assets leaving | NFT redistribution |
| Participant in-degree | Distinct pre-deposit participant keys reaching the node | Independent study convergence |
| Gross lovelace in/out | Sum before removing self-change | Throughput |
| External lovelace in/out | Sum after removing same-cluster change | External flow estimate |
| Active span | First to last observed transaction | Persistence |
| Median holding time | Time between tracer arrival and its next spend | Deposit, hot, or cold behavior |

Count distinct neighbors, transactions, tracers, and participant keys
separately. Reporting only one number hides whether apparent activity came
from many participants or repeated movements by one wallet.

### 5. Produce a starter forensic summary

Before expanding a cluster, summarize the seed population. This gives the user
scale, denominators, and obvious anomalies.

Report:

- number of tracer assets examined;
- number and percentage with a valid labelled deposit;
- number and percentage with untagged direct movements;
- number currently held, resting at a deposit address, or swept onward;
- distinct pre-deposit wallet-cluster keys;
- distinct current terminus keys;
- distinct reported exchange names;
- labelled tracer and participant-vote counts for each name;
- first and last observed tracer transaction;
- median and mean hops after the deposit boundary;
- median and mean time from deposit to first onward movement.

For transaction value, use the lovelace in the exact output carrying the
tracer. Do not describe the NFT itself as having that value. A Cardano native
asset does not carry an on-chain market price, and each tracer's token quantity
is always `1`.

Calculate:

```text
attached ADA per movement
  = lovelace in the tracer-bearing output / 1,000,000

mean attached ADA
  = sum of tracer-bearing output lovelace / tracer movements / 1,000,000

median attached ADA
  = median tracer-bearing output lovelace / 1,000,000
```

Report the median, mean, minimum, maximum, and sample count together. The mean
alone can be dominated by one large transfer. Cardano's minimum-output rules
also mean attached ADA is partly transaction mechanics, not necessarily
payment consideration.

For each transaction carrying a tracer, also summarize:

- input count and distinct input wallet keys;
- output count and distinct output wallet keys;
- transaction fee;
- tracer-bearing output index and attached ADA;
- total native-asset count in the tracer-bearing output;
- number of other tracer assets moved in the same transaction;
- same-cluster change-output count and value;
- external output count and value;
- elapsed time since the tracer's preceding movement.

Useful population statistics include:

| Statistic | Calculation | Why it helps |
|---|---|---|
| Mean inputs per tracer transaction | Total input count divided by carrying transactions | Detects consolidation-heavy transactions |
| Mean outputs per tracer transaction | Total output count divided by carrying transactions | Detects batching and fan-out |
| Multi-tracer transaction rate | Carrying transactions with more than one tracer divided by all carrying transactions | Detects NFT aggregation |
| Same-cluster change ratio | Same-cluster output lovelace divided by all output lovelace | Separates self-change from external flow |
| Sweep rate | Deposited tracers spent onward divided by deposited tracers | Distinguishes resting deposits from active aggregation |
| Median time to sweep | Median time from deposit output to its spend | Describes operational cadence |
| Terminus concentration | Largest terminus tracer count divided by all scoped tracers | Shows whether paths converge strongly |
| Participant concentration | Largest participant's tracer count divided by all scoped tracers | Reveals whether volume comes from one source |
| Label coverage | Labelled deposits divided by all scoped tracer entries | Shows how much attribution comes from messages |
| Conflict rate | Labelled tracers reaching a cluster whose resolved name differs divided by labelled tracers | Surfaces mistaken or dissenting reports |

For a fungible native asset included in a user's wider query, report token
quantity separately from ADA attached to its output. State the policy ID,
asset name, decimals convention if known, transfer count, total quantity,
mean, median, minimum, and maximum quantity per transfer. Do not infer a fiat
or ADA price without a separately sourced market or DEX valuation method.

A compact starter result can use this shape:

```json
{
  "scope": {
    "tracers": 0,
    "participants": 0,
    "from": "<ISO-8601>",
    "to": "<ISO-8601>"
  },
  "deposits": {
    "labelled": 0,
    "untaggedCandidates": 0,
    "swept": 0,
    "resting": 0
  },
  "movement": {
    "meanHopsAfterDeposit": 0,
    "medianHopsAfterDeposit": 0,
    "medianHoursToSweep": 0
  },
  "attachedAda": {
    "samples": 0,
    "mean": 0,
    "median": 0,
    "minimum": 0,
    "maximum": 0
  },
  "transactionShape": {
    "meanInputs": 0,
    "meanOutputs": 0,
    "multiTracerRate": 0,
    "sameClusterChangeRatio": 0
  },
  "convergence": {
    "termini": 0,
    "largestTerminusShare": 0,
    "labelConflictRate": 0
  }
}
```

Keep raw counts beside every percentage or rate. A rate without its numerator
and denominator is difficult to audit and easy to misread.

### 6. Classify shapes, not identities

Use several signals together:

- A deposit candidate usually has low degree, receives from one participant,
  and soon sweeps into a recurring higher-degree node.
- An aggregation or hot candidate has high distinct-source in-degree,
  repeated tracer convergence, substantial transaction activity, and
  recurring onward batching.
- A distribution candidate has high out-degree and repeated multi-output
  transactions.
- A cold or terminal candidate can have strong cumulative in-degree, low
  recent out-degree, long holding times, and a Byron `DdzFF` or `Ae2` address.
- A self-churn node has high gross throughput but much lower external flow
  after same-cluster outputs are removed.

Choose thresholds from the scoped population or publish the absolute values.
There is no universal degree threshold that proves an exchange.

### 7. Grow clusters conservatively

Start from the strongest available seed:

1. a valid label-backed tracer deposit;
2. a cited exchange address;
3. an untagged tracer converging into an already supported node;
4. an unattributed high-convergence candidate.

Expand one transaction or exact NFT hop at a time. Add a node to the same
candidate cluster only when at least one stated rule supports it, such as:

- repeated exact tracer convergence;
- the same dominant sweep destination across distinct deposit addresses;
- a shared wallet-cluster key;
- repeated, time-separated batching between the nodes;
- overlap with independently labelled deposits.

Stop expansion at:

- a node independently attributed to another exchange;
- a high-degree foreign hub that merely transacts with the candidate;
- a protocol or script address with a different structural role;
- a repeated node;
- the declared hop, date, or transaction cap.

Record cross-boundary transactions as links. Do not merge both sides merely
because they transact.

### 8. Use time as part of the graph

Calculate degree and convergence in explicit windows. A deposit address can
look inactive over its lifetime but have a clear deposit-to-sweep pattern
within hours. A hot wallet can migrate, and a historical exchange address may
later become dormant.

For each cluster, retain:

- first and last tracer contact;
- first and last transaction in the query window;
- tracer arrival and departure times;
- rolling distinct-source in-degree;
- changes in recurring sweep destinations.

When comparing runs, hold the node-key, edge-type, time-window, and
self-change rules constant.

### 9. Publish an auditable topology result

Return:

- the seed and why it was selected;
- nodes with addresses, cluster keys, roles, and degree measures;
- transaction-backed edges with evidence types;
- exact tracer membership;
- label votes and conflicts;
- expansion and stop rules;
- caps, provider coverage, and query time;
- which conclusions are exact, heuristic, or unresolved.

A useful cluster claim reads: "Five distinct pre-deposit wallet keys sent ten
labelled Kraken tracers that converged at this wallet cluster." It should not
read: "This address belongs to Kraken" unless independent evidence directly
supports that attribution.
