chain-insights 0.66.2 → 0.67.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "chain-insights",
3
- "version": "0.66.2",
3
+ "version": "0.67.2",
4
4
  "description": "AML investigation CLI and MCP proxy for blockchain risk screening and Chain Insights Graph access",
5
5
  "homepage": "https://chain-insights.ai",
6
6
  "repository": {
@@ -91,6 +91,9 @@
91
91
  "typescript": "^7.0.2",
92
92
  "vitest": "^5.0.3"
93
93
  },
94
+ "chainInsights": {
95
+ "dexRegistryVersion": 1
96
+ },
94
97
  "overrides": {
95
98
  "ws": "8.21.0",
96
99
  "proxy-addr": "2.0.8"
@@ -0,0 +1,178 @@
1
+ ---
2
+ name: chain-insights-dex
3
+ description: Use when a question names a decentralized exchange by name with no address — Aero, Aerodrome, Velodrome, up., Raphael, Topaz, Uniswap, Balancer, PancakeSwap, Trader Joe, Curve, Metric, Penguin — or asks who trades on, sold into, bought from or provides liquidity on an exchange or a DEX, which pools an exchange has, or how to trace money through a swap.
4
+ ---
5
+
6
+ # Chain Insights: exchanges by name
7
+
8
+ Load `chain-insights-cypher` first. Its answer rules hold here, and these
9
+ four hold even when it cannot load:
10
+
11
+ - Write every address in full, 42 characters, every time. Never shorten
12
+ one with `…` or `...`, not even for a repeat mention.
13
+ - A transfer moves tokens: "tokens worth about N USD", never "sent N USD".
14
+ Write USD after the number, never a dollar sign.
15
+ - Never print the query, its `USE` line or its `LIMIT` in the answer. Write
16
+ a time from its `_utc` twin.
17
+ - No drawn graph in text.
18
+
19
+ This skill turns an exchange's name into the addresses a query needs, finds
20
+ the exchange's pools, and follows the plain trail. Three trail-type skills
21
+ add the step past the contract a swap names:
22
+
23
+ | Trail | The contract past the swap | Load |
24
+ |---|---|---|
25
+ | plain | none: the swap's recipient is the buyer | this skill |
26
+ | gauge | a router | `chain-insights-dex-gauge` |
27
+ | vault | one pool manager that holds every pool | `chain-insights-dex-vault` |
28
+ | launchpad | a bonding curve, then its first pool | `chain-insights-dex-launchpad`, or `chain-insights-virtuals` for Virtuals |
29
+
30
+ The queries are in [reference.md](reference.md).
31
+
32
+ ## The memo
33
+
34
+ The memo below is rendered from the brand registry. Every address in it is
35
+ in full. Never edit it by hand.
36
+
37
+ <!-- brands:start -->
38
+ Memo of the brand registry, version 1, robinhood, recorded 2026-10-23.
39
+
40
+ | Brand | Key | Also written | Trail | Factories, or the manager | Router | Note |
41
+ |---|---|---|---|---|---|---|
42
+ | Aero (Aerodrome and Velodrome, merged) | `aero` | Aero, Aerodrome, Velodrome, AERO, Aero Slipstream | gauge | `0xc63d7338c178e805c544b8f897066bd3bbcbe136` | `0x72e46c9edf828002fdbfdd0952419790576c0f18`, `0x0fef9e88a7b76bcdbf451780c6774fe32965ee98`, `0x9ee35bf1bd69a03c6f0393582030fce8bb93d418` | |
43
+ | up. | `up` | up., up, UP, up33, UP33, up.finance | gauge | `0x1ac9db4a2608ba45d6127b1737949b51bb54b7f3`, `0xfa5429aeba338bea2bfcc1b9a889862ee395bc28` | `0xc062b870e813fca720f1e002c234369ab3ab9415`, `0xf5198743240fac98db71868f34c70139b1eb0474` | |
44
+ | Alandale | `alandale` | Alandale, LUTE, alandale.xyz | gauge | `0x2fadf533d9a098310007978730554f842547fc5f` | `0x8971d5a8f950f021e97583855925b021bfae2b35` | |
45
+ | Raphael Exchange | `raphael` | Raphael, RAPH, Raphael Exchange, Raphael Finance | gauge | `0x5481864ddd46a2d798df0925c23b7846e776e5e3`, `0x1a6745f84099fa7e84d1f3b34c23482865194bd1` | `0x2f0e010edc989bb4dc3bfaf07750480bc16285d4` | |
46
+ | Sheriff | `sheriff` | Sheriff, Sheriff Exchange, sheriff.exchange | gauge | `0x9ac30d72168a4498ae5c80226f4d3c86278e8f80` | `0xcb0615a1478838dea20e57447309be97f45dca0f` | |
47
+ | Topaz DEX | `topaz` | Topaz, TOPAZ, Topaz DEX, topazdex.com | gauge | `0xaa5865dc3a60b25d305226d66fd573021f0d8ffb` | `0x2e7395a6e0de6ee1f390bece891069cd18ff8572` | |
48
+ | Kittenswap | `kittenswap` | Kittenswap, KITTEN, KittenSwap | gauge | `0x45362763166cfed6174d312fa1449ea1fc37988a` | `0x7064c7bb85979f008212877c4ce41285ddf5374c` | |
49
+ | Morpheus | `morpheus` | Morpheus, Morpheus Farm | gauge | `0xd7cb0e0692f2d55a17ba81c1fe5501d66774fc4a` | none proven yet | |
50
+ | SwapHood | `swaphood` | SwapHood, SwapHood Finance, SWT, swaphood.finance | gauge | `0xe7206ecac3a51afe7e6179182ad4130a26068dd1` | `0x8f8056fec03159ebcc4aee1b8ea5a61d8fe405fc` | |
51
+ | Uniswap v2 | `uniswap-v2` | Uniswap v2, Uni v2 | plain | `0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f` | none | |
52
+ | Uniswap v3 | `uniswap-v3` | Uniswap v3, Uni v3 | plain | `0x1f7d7550b1b028f7571e69a784071f0205fd2efa` | none | |
53
+ | Uniswap v4 | `uniswap-v4` | Uniswap, UNI, Uniswap v4, Uni v4, PoolManager | vault | manager `0x8366a39cc670b4001a1121b8f6a443a643e40951` | the manager | |
54
+ | PancakeSwap Infinity | `pancakeswap` | PancakeSwap, Pancake, CAKE, PancakeSwap Infinity | vault | manager `0xee04c68742e6bf434be8039580d2e89bbe55bc6f` | the manager | |
55
+ | PancakeSwap v2 | `pancakeswap-v2` | PancakeSwap v2, Pancake v2 | plain | `0x02a84c1b3bbd7401a5f7fa98a384ebc70bb5749e` | none | |
56
+ | PancakeSwap v3 | `pancakeswap-v3` | PancakeSwap v3, Pancake v3 | plain | `0x0bfbcf9fa4f9c56b0f40a671ad40e0805a091865` | none | |
57
+ | SushiSwap V4 | `sushiswap` | Sushi, SushiSwap, SUSHI, Sushi V4 | vault | manager `0x81d732702f87d2d652ae79e9f52bf44928eca210` | the manager | |
58
+ | Orvex | `orvex` | Orvex, Orvex MetaDEX, orvex.fi, ORVX | vault | manager `0xd01c774d4a66408326bc65728ac5ae5aaf004032` | the manager | |
59
+ | Swaap v2 | `swaap` | Swaap, Swaap Finance, swaap.xyz | vault | manager `0xd315a9c38ec871068fec378e4ce78af528c76293` | the manager | |
60
+ | unnamed Balancer v3 vault | `balancer-v3` | Balancer v3 vault | vault | manager `0x28082618ba2073e602230188e4f4c46e9b2169eb` | the manager | |
61
+ | Ramses | `ramses` | Ramses, Ramses Exchange, RAM, ramses.xyz, Ramses DLMM | plain | `0xdcd5f77697914e27f56fd263ef82923c8524abac`, `0x43b2bf9f33036a02fc7a00935571c2a6b0108e66` | `0xd0019e86edb35e1fedaab03aed5c3c60f115d28b` | |
62
+ | SectorOne | `sectorone` | SectorOne, SectorOne DLMM | plain | `0x3d8dc63ddc9b992cfde89f7aea6f18717e84687d` | none | |
63
+ | Hoodit | `hoodit` | Hoodit, hoodit.xyz | plain | `0x22602d966defd638ee94e97a92e2eb0934c3fe1b` | none | |
64
+ | GIGA | `giga` | GIGA, GIGA DEX, GigaDEX, gigadex.fi | plain | `0x6fdf38f92ead1adfc04b73aaa947ab254f6c0916` | none | |
65
+ | Flap | `flap` | Flap, Flap launchpad, flap.sh | launchpad | `0x0d1ebb179cdbca88d74c923c4255cb2b17474afd` | none | |
66
+ | Curve | `curve` | Curve, Curve Finance, CRV, curve.finance | plain | `0x8271e06e5887fe5ba05234f5315c19f3ec90e8ad` | none | |
67
+ | Metric | `metric` | Metric, Metric OMM, metric.xyz | plain | `0x2e0a99a2e352043d1ca489cf45bf7b511bccc738` | none | |
68
+ | Penguin | `penguin` | Penguin, Penguin launchpad | launchpad | `0x09f1b640d53c9c4c1807bf5aa306745128ee4375` | none | |
69
+ | pons | `pons` | pons, pons launchpad | launchpad | `0x7ed598bcef8bd9edd8c97a195c6d13f40801ec7e` | none | |
70
+ | Virtuals Protocol | `virtuals` | Virtuals, VIRTUAL, Virtuals Protocol | launchpad | `0xfc2e4da3edb2e18100473339c763705d263d20a9` | none | |
71
+ <!-- brands:end -->
72
+
73
+ ## Name the exchange: memo, then the graph, never the user
74
+
75
+ The user names an exchange and no address. Every address the question needs
76
+ is in the memo or in the graph. **Never ask the user for a pool, factory or
77
+ router address.**
78
+
79
+ 1. **The memo.** Compare the name with the key and the "Also written"
80
+ column after dropping case, spaces, dots and hyphens: "alan dale" is
81
+ Alandale, "up." is up, "uni v4" is Uniswap v4. Take a typo that is one or
82
+ two letters away from one entry ("areo", "Aerodome", "pancakswap"), and
83
+ say which you took in one line: "I took Aero for areo." Then go on; ask
84
+ nothing.
85
+ 2. **The graph's brand list**, only when the memo has no match or the memo's
86
+ factories gave zero pools, and only when the lane can search: read
87
+ `Head` first (`USE chain MATCH (h:Head) RETURN h.behind_dex LIMIT 1`).
88
+ When `behind_dex` is at most 100000, read the brands the graph serves
89
+ (reference R2) and match the name the same way; say which brand you took.
90
+ When it is larger, or the read comes back `family_behind`,
91
+ `anchor_missing` or `query_timeout`, the lane cannot search by brand now:
92
+ say so in one line and go to 3. Never send that read twice.
93
+ 3. **Not covered.** When the memo and the brand list both lack the name, say
94
+ so in one line and list the covered brands by name: "Kyber is not covered
95
+ yet. Covered: Aero, up., Uniswap v4, …". **Send no query for the name.**
96
+ The graph has no name search: a `p.name CONTAINS`, a `labels CONTAINS`,
97
+ a scan of `:Launchpad`, `:Protocol` or `:Pool` by a word, and a count of
98
+ `SWAPPED` families all walk the whole chain and are stopped at 10 s or
99
+ refused. Twenty such reads cost the user four minutes and answer nothing.
100
+
101
+ Rules for the match:
102
+
103
+ - A name with no version takes every row it fits. "Balancer" is Balancer v2
104
+ and Balancer v3: read both in one batch and say so. "Uniswap" is the
105
+ Uniswap v4 row; say that Uniswap v3 and v2 are separate rows.
106
+ - Never guess a brand from a token name, a pool name or a symbol.
107
+ - An adapter mark in a pool's `labels`, such as `cl-gauge-v1`, is the
108
+ indexer's reading of a pool family, never a brand: two brands can share
109
+ one. Never find a brand's pools by searching the whole chain for a mark.
110
+ - Virtuals is a launchpad row of the memo. A question that names Virtuals,
111
+ VIRTUAL or a Virtuals agent loads `chain-insights-virtuals`, and this skill
112
+ adds nothing.
113
+
114
+ ## Find the pools of a brand
115
+
116
+ Send one `graph_query_batch`, in this order:
117
+
118
+ 1. **By memo factory** (reference R3): one batch member per factory of the
119
+ row, each anchored on its factory. Anchored reads are always admitted and
120
+ answer in under 100 ms. Merge the members into one ranking by volume. A
121
+ brand with three factories is three members of one batch, never three
122
+ turns.
123
+ 2. **By brand** (reference R1), only when the memo has no row for the name
124
+ or its factories gave zero pools, and only when `Head` says
125
+ `behind_dex` is at most 100000: the `:Pool` nodes that carry the brand,
126
+ ranked by lifetime volume. When the memo's factory gave zero pools and
127
+ the brand gave pools, answer from the graph and say the memo was behind.
128
+ A `family_behind`, `anchor_missing` or `query_timeout` ends this read:
129
+ say the lane cannot search by brand now, and never send it again.
130
+ 3. **By manager** for a vault row: a pool manager deploys nothing. Load
131
+ `chain-insights-dex-vault`, which reads the pools from the swaps the
132
+ manager settles.
133
+
134
+ A pool with no volume yet has no `total_volume_usd` and is left out of the
135
+ ranking. Name each pool in full with its lifetime volume: "tokens worth about
136
+ 228,559,848 USD over its life". A pool's `labels` carry the adapter mark; say
137
+ "an Aero pool", never the mark.
138
+
139
+ ## The plain trail
140
+
141
+ For a `plain` row (Metric, Curve, Trader Joe, Uniswap v3), a swap pays the
142
+ pool and the pool pays the buyer:
143
+
144
+ ```
145
+ seller ──FLOWS_TO──▶ pool seller ──SWAPPED──▶ buyer
146
+ ```
147
+
148
+ 1. **Sellers into the pool** (reference R4): the senders of the pool on
149
+ `FLOWS_TO`, ranked by lifetime volume. A seller that is a contract is
150
+ often an aggregator or a router: say "a contract", never "a trader". A
151
+ sender that also adds liquidity to the pool pays its deposits on this
152
+ link: it is a liquidity provider, not a seller.
153
+ 2. **Who bought** (reference R5): the seller's `SWAPPED` links. Keep the
154
+ links whose `pools` hold the pool. The recipient is the buyer: an account
155
+ that is not the seller is someone the seller paid through the swap. When
156
+ it is an account, send no second read.
157
+ 3. **When the recipient is a contract**, look it up in the memo. A router of
158
+ a gauge row loads `chain-insights-dex-gauge`. A pool manager of a vault
159
+ row loads `chain-insights-dex-vault`. Never call that contract the buyer.
160
+ 4. **The events** behind a link (reference R6): the facts `SWAP` rows of the
161
+ seller and the recipient on one day. The day comes from the link's
162
+ `last_seen_height`, read as a block on `USE chain` (reference R7).
163
+
164
+ ## How to answer
165
+
166
+ - Lead with the brand you took and its pools, then the sellers, the swap's
167
+ recipient named for what it is (the buyer, the router, the pool manager),
168
+ and the next lead.
169
+ - **The next lead.** End with who to trace next: the buyer's biggest
170
+ receivers, or the seller's first funders. Both are the newest-links read of
171
+ `chain-insights-cypher`, anchored on that one address.
172
+ - A pool's volume and a link's totals are lifetime totals. The money of one
173
+ day is a facts read of a pair and that day.
174
+ - Zero rows on the memo path is not "no pools": go to the graph's brand list
175
+ when the lane can search, before you say anything is missing.
176
+ - A refusal is an answer: `family_behind`, `anchor_missing` and
177
+ `query_timeout` say the lane cannot search the whole chain now. Say that in
178
+ one line and go on with the anchored reads. Never rephrase the same search.
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: 'Chain Insights Exchanges'
3
+ short_description: 'Find an exchange by name, its pools, and who traded on them'
4
+ default_prompt: 'Load chain-insights-cypher first. For a question that names an exchange on robinhood, resolve the name from the memo in this skill, then from the brands the graph serves, and never ask the user for an address. Find the pools by brand, then by the memo factories, load the trail-type skill the memo names, and use the tested queries in reference.md.'
@@ -0,0 +1,85 @@
1
+ # Exchange queries (Robinhood Chain)
2
+
3
+ Change only the values: the brand key, an address from the memo in
4
+ [SKILL.md](SKILL.md) or from a row you read, a day, a block. Every address
5
+ stays in full. Send related reads in one `graph_query_batch`.
6
+
7
+ ## R1. Pools of a brand, by the brand the graph serves
8
+
9
+ ```cypher
10
+ USE topology
11
+ MATCH (p:Pool {brand: "aero"}) WHERE p.total_volume_usd IS NOT NULL
12
+ RETURN p.address AS to_address, p.labels AS to_labels, p.total_volume_usd AS total_volume_usd, p.tx_total_count AS tx_total_count ORDER BY p.total_volume_usd DESC LIMIT 10
13
+ ```
14
+
15
+ Zero rows means the lane does not serve the brand yet, or the brand is not
16
+ this key. Go to R3 with the memo's factories, and R2 when the memo has no row.
17
+
18
+ ## R2. The brands the graph serves
19
+
20
+ ```cypher
21
+ USE topology
22
+ MATCH (p:Pool) WHERE p.brand IS NOT NULL
23
+ RETURN DISTINCT p.brand AS brand LIMIT 50
24
+ ```
25
+
26
+ ## R3. Pools of a brand, by one memo factory
27
+
28
+ One batch member per factory of the row, each with its own `id`. Merge the
29
+ members into one ranking by `total_volume_usd`.
30
+
31
+ ```cypher
32
+ USE topology
33
+ MATCH (f:Address {address: "0xc63d7338c178e805c544b8f897066bd3bbcbe136"})-[:DEPLOYED_CONTRACT]->(p:Pool) WHERE p.total_volume_usd IS NOT NULL
34
+ RETURN f.address AS from_address, p.address AS to_address, p.labels AS to_labels, p.total_volume_usd AS total_volume_usd, p.tx_total_count AS tx_total_count ORDER BY p.total_volume_usd DESC LIMIT 10
35
+ ```
36
+
37
+ Trader Joe has three factories: three members of one batch.
38
+
39
+ ```json
40
+ {"network": "robinhood", "queries": [
41
+ {"id": "trader-joe-1", "query": "<R3 with 0xdcd5f77697914e27f56fd263ef82923c8524abac>"},
42
+ {"id": "trader-joe-2", "query": "<R3 with 0x3d8dc63ddc9b992cfde89f7aea6f18717e84687d>"},
43
+ {"id": "trader-joe-3", "query": "<R3 with 0x22602d966defd638ee94e97a92e2eb0934c3fe1b>"}
44
+ ]}
45
+ ```
46
+
47
+ ## R4. Sellers into one pool
48
+
49
+ The senders of the pool, ranked by lifetime volume. A pool never sends on
50
+ this read: the pool trace rule leaves a pool only on `REMOVED_LIQUIDITY`.
51
+
52
+ ```cypher
53
+ USE topology
54
+ MATCH (s:Address)-[f:FLOWS_TO]->(p:Address {address: "0x7615926023bb149f36095645c2a81dc367d39750"}) WHERE NOT s:Pool
55
+ RETURN s.address AS from_address, p.address AS to_address, labels(s) AS from_node_labels, f.amount_usd_sum AS amount_usd_sum, f.tx_count AS tx_count, f.first_seen_timestamp AS first_seen_timestamp, f.last_seen_timestamp AS last_seen_timestamp, s.labels AS from_labels, p.labels AS to_labels, s.is_exchange AS from_is_exchange, p.is_exchange AS to_is_exchange ORDER BY f.amount_usd_sum DESC LIMIT 25
56
+ ```
57
+
58
+ ## R5. Who a seller's swaps paid
59
+
60
+ Anchored on the seller. Keep the rows whose `pools` hold the pool you
61
+ started from: filter them yourself, never in the query.
62
+
63
+ ```cypher
64
+ USE topology
65
+ MATCH (s:Address {address: "0x4b9364c8553c519a419b259f022865071fd7bfdf"})-[sw:SWAPPED]->(r:Address)
66
+ RETURN s.address AS from_address, r.address AS to_address, labels(r) AS to_node_labels, sw.sold_asset AS sold_asset, sw.bought_asset AS bought_asset, sw.sold_usd AS sold_usd, sw.bought_usd AS bought_usd, sw.swap_count AS swap_count, sw.pools AS pools, sw.last_seen_height AS last_seen_height ORDER BY sw.swap_count DESC LIMIT 25
67
+ ```
68
+
69
+ ## R6. The swaps of a seller and a recipient on one day
70
+
71
+ ```cypher
72
+ USE facts
73
+ MATCH (s:Address {address: "0x4b9364c8553c519a419b259f022865071fd7bfdf"})-[x:SWAP]->(r:Address {address: "0x72e46c9edf828002fdbfdd0952419790576c0f18"}) WHERE x.block_date = "2026-10-22"
74
+ RETURN x.tx_id AS tx_id, x.block_timestamp AS block_timestamp, x.payer AS payer, x.recipient AS recipient, x.sold_asset_symbol AS sold_asset_symbol, x.sold_usd AS sold_usd, x.bought_asset_symbol AS bought_asset_symbol, x.bought_usd AS bought_usd LIMIT 50
75
+ ```
76
+
77
+ ## R7. The day of a block
78
+
79
+ A `SWAPPED` link carries heights, not times. Read the block of
80
+ `last_seen_height` for its day.
81
+
82
+ ```cypher
83
+ USE chain
84
+ MATCH (b:Block {block_height: 95254047}) RETURN b.block_date, b.block_timestamp
85
+ ```
@@ -0,0 +1,136 @@
1
+ ---
2
+ name: chain-insights-dex-gauge
3
+ description: Use for the dex-gauge trail - exchanges whose swaps go through a router and whose liquidity is staked in gauges, such as Aero (Aerodrome, Velodrome), up., Raphael and Topaz on robinhood - when a question asks who sold into a pool of one of them, who bought, who provides liquidity or took the most out, or who to trace next past the router. Loaded by chain-insights-dex for a gauge row of its memo.
4
+ ---
5
+
6
+ # Chain Insights: the gauge trail (Aero, up., Raphael, Topaz)
7
+
8
+ Load `chain-insights-cypher` first, then `chain-insights-dex` for the memo:
9
+ the brand's factories, its router and its pools come from there. Their answer
10
+ rules hold here: every address in full, tokens worth an amount in USD, no
11
+ query text in the answer, times from the `_utc` twins.
12
+
13
+ On a gauge exchange a swap usually goes through the exchange's **router**.
14
+ The pool pays the router, and the router pays on in the same transaction:
15
+
16
+ ```
17
+ seller ──FLOWS_TO──▶ pool ──▶ router ──▶ buyer
18
+ │
19
+ └── SWAPPED from the seller names the router
20
+ ```
21
+
22
+ So the `SWAPPED` recipient of a seller is often the router. **The router is
23
+ not the buyer.** Name it "the Aero router", in full, and read the buyer from
24
+ the router's own transfer in the seller's transaction.
25
+
26
+ ## Sellers and the buyer, in order
27
+
28
+ 1. **The pool.** Take it from `chain-insights-dex` (pools by brand, then by
29
+ memo factory). The busiest Aero pool is
30
+ `0x7615926023bb149f36095645c2a81dc367d39750`.
31
+ 2. **Sellers into the pool** (G1): its senders on `FLOWS_TO`, ranked by
32
+ lifetime volume. Most of the biggest are contracts: aggregators,
33
+ routers and liquidity managers. Say "a contract", never "a trader". A
34
+ sender that also adds liquidity to the pool (G6) pays its deposits on
35
+ this link: it is a liquidity provider, not a seller. On the busiest Aero
36
+ pool the two biggest senders,
37
+ `0x2192bc3b4028acc1113f2cd9ac2cba70c36520db` and
38
+ `0xc2eedf3bc7f93366c00c6074df0e6f122fa2445c`, are liquidity managers.
39
+ 3. **The seller's swaps** (G2): its `SWAPPED` links. Keep the rows whose
40
+ `pools` hold the pool; filter them yourself. Note the recipient and the
41
+ `last_seen_height`.
42
+ 4. **The recipient is an account** that is not the seller: that is the buyer.
43
+ Stop here. **The recipient is the memo's router**: go on.
44
+ 5. **The day** (G3): the block of `last_seen_height` on `USE chain` gives its
45
+ `block_date`.
46
+ 6. **The seller's swap on that day** (G4): the facts `SWAP` rows of the
47
+ seller and the router on that day give each swap's `tx_id` and its sold
48
+ and bought assets.
49
+ 7. **The buyer** (G5): the router's facts `TRANSFER` rows of that day with
50
+ that `tx_id`. The receiver of the bought asset is the buyer. A receiver
51
+ that is a pool or a pool manager, of another asset, is the next leg of the
52
+ route, not the buyer. When no row carries the bought asset, say the
53
+ router's payout is not in the transfers read, name the router as router,
54
+ and stop: never guess the buyer.
55
+
56
+ ## Liquidity providers, and the gauge
57
+
58
+ - **Who provided** (G6): the `ADDED_LIQUIDITY` links into the pool, one per
59
+ party and asset. Sum `usd` per party yourself.
60
+ - **Who took the most out** (G7): the `REMOVED_LIQUIDITY` links out of the
61
+ pool, summed per receiver, with what the same receiver added.
62
+ - **The gauge.** On these exchanges a provider can stake its position in the
63
+ exchange's gauge to earn rewards. The party on a link can then be a
64
+ contract (the position manager or the gauge), not the person. Say so, name
65
+ the contract in full, and never call it the provider. The person is the
66
+ sender of that transaction, read on `USE chain` by its `tx_id`.
67
+
68
+ ## The next lead
69
+
70
+ End every answer with who to trace next, in one short paragraph:
71
+
72
+ - the buyer's biggest receivers, the newest-links read of
73
+ `chain-insights-cypher` anchored on the buyer, sorted by `amount_usd_sum`;
74
+ - for a seller that is a contract, the accounts that paid it: the same read
75
+ with the arrow flipped.
76
+
77
+ Never walk out of the router or the pool on `FLOWS_TO`: the router has
78
+ thousands of receivers, and the buyer is noise there.
79
+
80
+ ## Queries
81
+
82
+ ### G1. Sellers into the pool
83
+
84
+ ```cypher
85
+ USE topology
86
+ MATCH (s:Address)-[f:FLOWS_TO]->(p:Address {address: "0x7615926023bb149f36095645c2a81dc367d39750"}) WHERE NOT s:Pool
87
+ RETURN s.address AS from_address, p.address AS to_address, labels(s) AS from_node_labels, f.amount_usd_sum AS amount_usd_sum, f.tx_count AS tx_count, f.first_seen_timestamp AS first_seen_timestamp, f.last_seen_timestamp AS last_seen_timestamp, s.labels AS from_labels, p.labels AS to_labels, s.is_exchange AS from_is_exchange, p.is_exchange AS to_is_exchange ORDER BY f.amount_usd_sum DESC LIMIT 25
88
+ ```
89
+
90
+ ### G2. One seller's swaps
91
+
92
+ ```cypher
93
+ USE topology
94
+ MATCH (s:Address {address: "0x4b9364c8553c519a419b259f022865071fd7bfdf"})-[sw:SWAPPED]->(r:Address)
95
+ RETURN s.address AS from_address, r.address AS to_address, labels(r) AS to_node_labels, sw.sold_asset AS sold_asset, sw.bought_asset AS bought_asset, sw.sold_usd AS sold_usd, sw.bought_usd AS bought_usd, sw.swap_count AS swap_count, sw.pools AS pools, sw.last_seen_height AS last_seen_height ORDER BY sw.swap_count DESC LIMIT 25
96
+ ```
97
+
98
+ ### G3. The day of the swap
99
+
100
+ ```cypher
101
+ USE chain
102
+ MATCH (b:Block {block_height: 95254047}) RETURN b.block_date, b.block_timestamp
103
+ ```
104
+
105
+ ### G4. The seller's swaps through the router on that day
106
+
107
+ ```cypher
108
+ USE facts
109
+ MATCH (s:Address {address: "0x4b9364c8553c519a419b259f022865071fd7bfdf"})-[x:SWAP]->(r:Address {address: "0x72e46c9edf828002fdbfdd0952419790576c0f18"}) WHERE x.block_date = "2026-10-22"
110
+ RETURN x.tx_id AS tx_id, x.block_timestamp AS block_timestamp, x.sold_asset_symbol AS sold_asset_symbol, x.sold_usd AS sold_usd, x.bought_asset_symbol AS bought_asset_symbol, x.bought_usd AS bought_usd LIMIT 50
111
+ ```
112
+
113
+ ### G5. The router's transfers in that transaction
114
+
115
+ ```cypher
116
+ USE facts
117
+ MATCH (r:Address {address: "0x72e46c9edf828002fdbfdd0952419790576c0f18"})-[t:TRANSFER]->(b:Address)
118
+ WHERE t.block_date = "2026-10-22" AND t.tx_id = "0xe8757773043832b6602baf86a42e14577205a25ac1fe1a07c48c717f2ff15d56"
119
+ RETURN r.address AS from_address, b.address AS to_address, t.amount_usd AS amount_usd, t.asset_symbol AS asset_symbol, t.kind AS kind, t.tx_id AS tx_id LIMIT 10
120
+ ```
121
+
122
+ ### G6. Who added liquidity to the pool
123
+
124
+ ```cypher
125
+ USE topology
126
+ MATCH (a:Address)-[l:ADDED_LIQUIDITY]->(p:Address {address: "0x7615926023bb149f36095645c2a81dc367d39750"})
127
+ RETURN a.address AS from_address, p.address AS to_address, labels(a) AS from_node_labels, l.asset AS asset, l.usd AS usd, l.event_count AS event_count, l.first_seen_height AS first_seen_height, l.last_seen_height AS last_seen_height ORDER BY l.usd DESC LIMIT 25
128
+ ```
129
+
130
+ ### G7. Who took the most out of the pool
131
+
132
+ ```cypher
133
+ USE topology
134
+ MATCH (p:Address {address: "0x7615926023bb149f36095645c2a81dc367d39750"})-[r:REMOVED_LIQUIDITY]->(b:Address)
135
+ RETURN p.address AS from_address, b.address AS to_address, sum(r.usd) AS removed_usd, max(r.receiver_added_usd) AS receiver_added_usd ORDER BY removed_usd DESC LIMIT 25
136
+ ```
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: 'Chain Insights Exchanges: router trail'
3
+ short_description: 'Sellers, the router and the real buyer on Aero, up. and other gauge exchanges'
4
+ default_prompt: 'Load chain-insights-cypher and chain-insights-dex first. Read the sellers into the pool, their swaps, and when the swap names the router, read the buyer from the router transfer of the same transaction on facts. Name the router as router, never as buyer, and end with the next lead.'
@@ -0,0 +1,94 @@
1
+ ---
2
+ name: chain-insights-dex-launchpad
3
+ description: Use for the dex-launchpad trail - token launchpads with a bonding curve on robinhood other than Virtuals, such as Penguin and the unnamed bonding-curve launchpad - when a question asks who launched a token there, who bought or sold on its curve, whether and when it graduated, or which pool it moved to. Loaded by chain-insights-dex for a launchpad row of its memo. Virtuals questions belong to chain-insights-virtuals.
4
+ ---
5
+
6
+ # Chain Insights: the launchpad trail (Penguin, bonding curves)
7
+
8
+ Load `chain-insights-cypher` first, then `chain-insights-dex` for the memo:
9
+ the launchpad's factory comes from there. Their answer rules hold here:
10
+ every address in full, tokens worth an amount in USD, no query text in the
11
+ answer, times from the `_utc` twins.
12
+
13
+ **Virtuals is not this skill.** A question that names Virtuals, VIRTUAL or a
14
+ Virtuals agent loads `chain-insights-virtuals`, which holds its own model.
15
+ Use nothing from here for it.
16
+
17
+ A launchpad token lives in two stages:
18
+
19
+ ```
20
+ creator ── one transaction ──▶ factory ──DEPLOYED_CONTRACT──▶ launched token
21
+ │ curve stage:
22
+ buyers ◀──────────────┤ bought and sold
23
+ │ against the curve
24
+ ▼ graduation
25
+ first pool on an exchange
26
+ ```
27
+
28
+ | Launchpad | Factory | What the factory deploys |
29
+ |---|---|---|
30
+ | Penguin | `0x09f1b640d53c9c4c1807bf5aa306745128ee4375` | the launched token, which is also its own curve |
31
+ | unnamed launchpad | `0x7ed598bcef8bd9edd8c97a195c6d13f40801ec7e` | a launch contract; its name is not proven yet |
32
+
33
+ Call the second one "an unnamed bonding-curve launchpad". Never give it a
34
+ name you have not read.
35
+
36
+ ## Who launched it
37
+
38
+ 1. **The launches** (L1): the factory's `DEPLOYED_CONTRACT` links, newest
39
+ first. The creator is `tx_origin` on the link, the sender of the creation
40
+ transaction. `deployer_address` is the factory: never call it the
41
+ creator.
42
+ 2. A Penguin token carries `penguin-launchpad` in its `labels`, and
43
+ `CurveLaunch` while it trades on the curve.
44
+
45
+ ## The curve stage
46
+
47
+ 3. **Who bought and sold on the curve** (L2): the launched contract's own
48
+ `FLOWS_TO` links, both directions, ranked by transactions. Money in is a
49
+ buy, money out is a payout. On Penguin the token contract is the curve,
50
+ so these are its traders.
51
+ 4. A fresh token has no price: its `amount_usd` can be empty. Value a buy by
52
+ what was paid for it, and say when no price exists.
53
+
54
+ ## Graduation and the first pool
55
+
56
+ 5. **The first pool** (L3): the launched contract's `ADDED_LIQUIDITY` links
57
+ into a `:Pool`, oldest first. The first one is the graduation: the curve's
58
+ money moved into an exchange pool.
59
+ 6. When L3 is empty, say the graduation is not in the graph yet. Never guess
60
+ a pool from the token's name.
61
+ 7. After graduation the token trades on that pool. Load `chain-insights-dex`
62
+ for the pool's brand and its trail.
63
+
64
+ ## The next lead
65
+
66
+ End with who to trace next: the creator's first funders (the newest-links
67
+ read of `chain-insights-cypher`, arrow flipped, sorted by
68
+ `first_seen_timestamp`), or the biggest early buyer's onward flows.
69
+
70
+ ## Queries
71
+
72
+ ### L1. Launches of one launchpad, newest first
73
+
74
+ ```cypher
75
+ USE topology
76
+ MATCH (f:Address {address: "0x09f1b640d53c9c4c1807bf5aa306745128ee4375"})-[d:DEPLOYED_CONTRACT]->(t:Address)
77
+ RETURN f.address AS from_address, t.address AS to_address, labels(t) AS to_node_labels, t.labels AS to_labels, d.tx_origin AS creator, d.tx_id AS tx_id, d.block_height AS block_height, d.block_timestamp AS created_timestamp ORDER BY d.block_height DESC LIMIT 25
78
+ ```
79
+
80
+ ### L2. Traders on the curve of one launched token
81
+
82
+ ```cypher
83
+ USE topology
84
+ MATCH (t:Address {address: "0xf3b01a81dc8a4216d92e74b40113e9e1b10a4dac"})-[f:FLOWS_TO]-(b:Address) WHERE NOT t:Pool
85
+ RETURN startNode(f).address AS from_address, endNode(f).address AS to_address, labels(b) AS node_labels, f.tx_count AS tx_count, f.amount_usd_sum AS amount_usd_sum, f.first_seen_timestamp AS first_seen_timestamp, f.last_seen_timestamp AS last_seen_timestamp ORDER BY f.tx_count DESC LIMIT 25
86
+ ```
87
+
88
+ ### L3. The first pool of one launched token
89
+
90
+ ```cypher
91
+ USE topology
92
+ MATCH (t:Address {address: "0xf3b01a81dc8a4216d92e74b40113e9e1b10a4dac"})-[l:ADDED_LIQUIDITY]->(p:Pool)
93
+ RETURN t.address AS from_address, p.address AS to_address, p.labels AS to_labels, l.asset AS asset, l.usd AS usd, l.first_seen_height AS first_seen_height ORDER BY l.first_seen_height ASC LIMIT 5
94
+ ```
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: 'Chain Insights Exchanges: launchpad trail'
3
+ short_description: 'Launches, curve traders and graduation on Penguin and other launchpads'
4
+ default_prompt: 'Load chain-insights-cypher and chain-insights-dex first. Read the launches from the factory, the creator from tx_origin, the curve traders from the launched contract, and the first pool from its liquidity. Hand every Virtuals question to chain-insights-virtuals.'
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: chain-insights-dex-vault
3
+ description: Use for the dex-vault trail - exchanges where one pool manager contract holds every pool, such as Uniswap v4, Balancer v2, Balancer v3 and PancakeSwap Infinity on robinhood - when a seller's swap names the pool manager or vault, when a question asks who bought past the manager, or which pools such an exchange has. Loaded by chain-insights-dex for a vault row of its memo.
4
+ ---
5
+
6
+ # Chain Insights: the vault trail (Uniswap v4, Balancer, PancakeSwap Infinity)
7
+
8
+ Load `chain-insights-cypher` first, then `chain-insights-dex` for the memo:
9
+ the brand's manager comes from there. Their answer rules hold here: every
10
+ address in full, tokens worth an amount in USD, no query text in the answer,
11
+ times from the `_utc` twins.
12
+
13
+ On a vault exchange one contract, the **pool manager** (Balancer calls it
14
+ the vault), holds the tokens of every pool. A swap pays the manager and the
15
+ manager pays out:
16
+
17
+ ```
18
+ seller ──SWAPPED──▶ pool manager ──▶ buyer
19
+ settles every pool
20
+ ```
21
+
22
+ So a seller's `SWAPPED` recipient is the manager. **The manager is not the
23
+ buyer.** Name it for what it is, in full: "the Uniswap v4 pool manager
24
+ `0x8366a39cc670b4001a1121b8f6a443a643e40951`", "the Balancer v2 vault
25
+ `0xd315a9c38ec871068fec378e4ce78af528c76293`".
26
+
27
+ | Exchange | Manager |
28
+ |---|---|
29
+ | Uniswap v4 | `0x8366a39cc670b4001a1121b8f6a443a643e40951` |
30
+ | Balancer v2 | `0xd315a9c38ec871068fec378e4ce78af528c76293` |
31
+ | Balancer v3 | `0x28082618ba2073e602230188e4f4c46e9b2169eb` |
32
+ | PancakeSwap Infinity | `0xd01c774d4a66408326bc65728ac5ae5aaf004032` |
33
+
34
+ ## The buyer past the manager
35
+
36
+ 1. **The seller's swaps** (V1): its `SWAPPED` links. A row whose recipient is
37
+ the manager is a vault swap. Note its `last_seen_height`.
38
+ 2. **The day** (V2): the block of that height on `USE chain`.
39
+ 3. **The facts `SWAP` row** (V3) of the seller and the manager on that day.
40
+ Its `recipient` names who received the bought asset:
41
+ - a `recipient` that is not the manager is the buyer;
42
+ - a `recipient` equal to the manager means the manager paid the seller
43
+ back: the seller is the buyer of its own swap. Say "the seller swapped
44
+ for itself".
45
+ 4. Name the sold and bought assets by their contracts in full, with "tokens
46
+ worth about N USD on DAY".
47
+
48
+ **Never take a topology hop out of the manager.** The Uniswap v4 pool
49
+ manager links to about 480,000 receivers. A read of its receivers, a walk
50
+ through it, or a ranking of where its money went times out or names noise.
51
+ The walk guard of `chain-insights-cypher` keeps `:Protocol` contracts out of
52
+ every walk for this reason.
53
+
54
+ ## The pools of a vault exchange
55
+
56
+ A manager deploys no pool, so there is no factory to anchor on. Its pools are
57
+ the `pools` of the swaps it settles:
58
+
59
+ 1. **The swaps into the manager** (V4): one hop in, anchored on the manager,
60
+ ranked by what was sold. Collect the `pools` of the rows: those are the
61
+ exchange's busiest pools among these swaps.
62
+ 2. **The events of one pool**: take one seller from V4 and read its facts
63
+ `SWAP` rows with the manager on one day (V3).
64
+ 3. A pool id here may name the pool, not a contract of its own. Say "a pool
65
+ of the Uniswap v4 pool manager", never "a pool contract".
66
+
67
+ ## The next lead
68
+
69
+ End with who to trace next: the buyer's biggest receivers, the newest-links
70
+ read of `chain-insights-cypher` anchored on the buyer. When the buyer is the
71
+ seller itself, trace the seller's onward flows instead.
72
+
73
+ ## Queries
74
+
75
+ ### V1. One seller's swaps
76
+
77
+ ```cypher
78
+ USE topology
79
+ MATCH (s:Address {address: "0x705da6eb557a987960294597954d75e9be2a1983"})-[sw:SWAPPED]->(r:Address)
80
+ RETURN s.address AS from_address, r.address AS to_address, labels(r) AS to_node_labels, sw.sold_asset AS sold_asset, sw.bought_asset AS bought_asset, sw.sold_usd AS sold_usd, sw.bought_usd AS bought_usd, sw.swap_count AS swap_count, sw.pools AS pools, sw.last_seen_height AS last_seen_height ORDER BY sw.swap_count DESC LIMIT 25
81
+ ```
82
+
83
+ ### V2. The day of the swap
84
+
85
+ ```cypher
86
+ USE chain
87
+ MATCH (b:Block {block_height: 95508039}) RETURN b.block_date, b.block_timestamp
88
+ ```
89
+
90
+ ### V3. The facts SWAP row past the manager
91
+
92
+ ```cypher
93
+ USE facts
94
+ MATCH (s:Address {address: "0x705da6eb557a987960294597954d75e9be2a1983"})-[x:SWAP]->(m:Address {address: "0x8366a39cc670b4001a1121b8f6a443a643e40951"}) WHERE x.block_date = "2026-10-22"
95
+ RETURN s.address AS from_address, m.address AS to_address, x.payer AS payer, x.recipient AS recipient, x.sold_asset AS sold_asset, x.sold_usd AS sold_usd, x.bought_asset AS bought_asset, x.bought_usd AS bought_usd, x.tx_id AS tx_id, x.block_timestamp AS block_timestamp LIMIT 50
96
+ ```
97
+
98
+ ### V4. The swaps the manager settles, and their pools
99
+
100
+ ```cypher
101
+ USE topology
102
+ MATCH (s:Address)-[sw:SWAPPED]->(m:Address {address: "0x8366a39cc670b4001a1121b8f6a443a643e40951"})
103
+ RETURN s.address AS from_address, m.address AS to_address, sw.sold_usd AS sold_usd, sw.swap_count AS swap_count, sw.pools AS pools, sw.last_seen_height AS last_seen_height ORDER BY sw.sold_usd DESC LIMIT 25
104
+ ```
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: 'Chain Insights Exchanges: pool manager trail'
3
+ short_description: 'The real buyer past the Uniswap v4, Balancer or PancakeSwap pool manager'
4
+ default_prompt: 'Load chain-insights-cypher and chain-insights-dex first. When a swap names the pool manager, name it as the manager and read the buyer from the recipient of the facts SWAP row of the seller and the manager on that day. Never take a topology hop out of the manager.'
@@ -57,8 +57,20 @@ differ: find them first, never reuse these.
57
57
  | VIRTUAL token | `0xc6911796042b15d7fa4f6cde69e245ddcd3d9c31` |
58
58
  | Launch contract | `0xd4ccbfa37e2f35611b3042e4096ad7a3459bd007` |
59
59
  | Token factory | `0x43e4c17b15365596caae8e7d00e42bc8e988c2d4` |
60
- | Starting-pool factory | `0xfc2e4da3edb2e18100473339c763705d263d20a9` |
61
- | Uniswap v2 pair factory | `0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f` |
60
+
61
+ The starting-pool (bonding) factory comes from the exchange memo, the row
62
+ `chain-insights-dex` lists under Virtuals. The public pair of a graduated
63
+ agent is created on Uniswap's own v2 factory
64
+ `0x8bceaa40b9acdfaedf85adf4ff01f5ad6517937f` (the memo's `uniswap-v2` row):
65
+ most of that factory's pairs are Virtuals agents.
66
+
67
+ <!-- brands:start -->
68
+ The factories of the brand registry, version 1, row `virtuals`:
69
+
70
+ | Factory | Address |
71
+ |---|---|
72
+ | factory | `0xfc2e4da3edb2e18100473339c763705d263d20a9` |
73
+ <!-- brands:end -->
62
74
 
63
75
  **Hubs.** These carry millions of transactions. Keep them out of buyer,
64
76
  funder and shared-wallet lists **by address**: the graph does not mark