chain-insights 0.56.11 → 0.56.12

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.56.11",
3
+ "version": "0.56.12",
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": {
@@ -24,8 +24,12 @@ The one case without the tool is at the end, Shell without the tool.
24
24
  time. A repeat mention is written in full too: `0xd4a9…` as a
25
25
  back-reference to an address named earlier is wrong, in a long answer most
26
26
  of all. When the user asks for shortened addresses "for readability",
27
- still write them in full and say the full form is the rule, because a
28
- shortened address cannot be copied or checked. When a table column or a
27
+ give them names instead: list each name with its full address once at the
28
+ top (Wallet A: 0x…, the vault: 0x…), then use the names in the sentences
29
+ and the table. The addresses stay in full, because a shortened address
30
+ cannot be copied or checked, and the user gets the readable answer they
31
+ asked for. Codex once shortened every address for the rest of a
32
+ conversation after such a request: that is wrong. When a table column or a
29
33
  row needs a short label, name the thing instead (Pair A, Wallet Y, the
30
34
  vault) and list each name with its full address just above the table:
31
35
  `To 0x00862568… pair` as a column header is wrong. When the user types a shortened address, take it as the one full
@@ -111,6 +115,7 @@ Find the question in this table. Send its first query, once, with the addresses
111
115
  | Biggest senders or receivers of one address | `topology` | Newest links of one address, `ORDER BY f.amount_usd_sum DESC LIMIT 10` |
112
116
  | How many, how much, first or last active, for one address | `topology` | Profile of one address |
113
117
  | The transfers of a pair on one day | `facts` | `TRANSFER` of the pair and the day, see Facts |
118
+ | What one address did in a month, since a date, in the last N days | topology, then facts | Links bounded by first and last seen, day reads only for the links that straddle an edge, see A window of days for one address |
114
119
  | What happened in this transaction hash? | `chain` | `Transaction {tx_id}`, see Chain |
115
120
  | The latest block, block N, how far behind the graph is | `chain` | `Head`, or `Block {block_height}` |
116
121
  | What fields does an Address have? | none | Call `meta_schema {network}`. Send no query. |
@@ -330,7 +335,7 @@ The server serves five read-only catalog calls: `CALL db.labels()`, `CALL db.rel
330
335
  - A facts read aggregates with `count()` and `sum()` only, over the whole page: no grouping key, no `min()`, `max()` or `avg()` (`unsupported facts query shape`). Read the rows and compute the rest yourself.
331
336
  - Every row and both endpoints carry `network`, the query's `network`. A filter on it is no anchor: it never replaces the pair and the day.
332
337
  - Facts serves no kind. A read that names `:Account` or `:Contract` is refused with `facts_no_anchor`: ask `USE topology` for the kind, or `USE chain` for `is_contract` and `nonce`.
333
- - A facts read covers one day. For more days, send one read for each day.
338
+ - A facts read covers one day. For more days, send one read for each day, and for a window of days around one address pick the pairs first (A window of days for one address, below): never every pair on every day.
334
339
  - Amounts and USD values come back as text, such as `"5.23661492"`. Convert them before you add them.
335
340
  - `TRANSFER` columns: `tx_id`, `block_date`, `block_height`, `block_timestamp`, `event_index`, `edge_index`, `kind`, `asset_contract`, `asset_symbol`, `amount`, `amount_usd`, `price_usd`, `price_missing`, `token_id`, `token_standard`, `operator_address`, `raw_amount` and `decimals`. `kind` is `token`, `native` or `internal`: an `internal` row is ETH a contract sends while it runs a call.
336
341
 
@@ -350,6 +355,40 @@ pair moved on one day, read its `TRANSFER` rows for that day, then:
350
355
  3. If a row's `price_missing` is true, show its amount and say no price exists for that asset. Never guess a USD value.
351
356
  4. Say "tokens worth about X USD on DAY", because the row moved tokens.
352
357
 
358
+ ### A window of days for one address
359
+
360
+ "What did this address do in September", "everything it received since
361
+ August 1", "only the last 7 days": never read every pair on every day. One
362
+ answer once took 72 reads and 189 seconds. Three steps, in this order:
363
+
364
+ 1. One topology read, both directions, bounded by the window: a link is in
365
+ the window when `f.first_seen_timestamp <= <window end ms>` and
366
+ `f.last_seen_timestamp >= <window start ms>`. Return `from_address`,
367
+ `to_address`, `tx_count`, `amount_usd_sum`, `first_seen_timestamp` and
368
+ `last_seen_timestamp`. This is the list of counterparties active in the
369
+ window.
370
+ 2. A link whose first and last seen both fall inside the window needs no
371
+ facts read: its lifetime `tx_count` and `amount_usd_sum` are the window
372
+ totals. Only a link that straddles a window edge needs the per-day
373
+ totals: for that pair, one `graph_query_batch` of one `count()` and
374
+ `sum()` query per day, up to 20 days per call, over the days between the
375
+ later of its first seen and the window start, and the earlier of its last
376
+ seen and the window end.
377
+ 3. Answer with the totals per counterparty, and say which are exact and
378
+ which came from the day reads. Read rows only for the days the user asks
379
+ about. When more than ten links straddle an edge, give the window picture
380
+ from the link totals, name the straddling pairs as estimates, and offer
381
+ the exact read for one of them.
382
+
383
+ The outgoing side, for September 2026; the incoming side is the same read
384
+ with the arrow reversed, and both go in one `graph_query_batch`:
385
+
386
+ ```cypher
387
+ USE topology
388
+ MATCH (a:Address {address: "0x9f73873740c799d74741ad2d15cee7fb33572e4a"})-[f:FLOWS_TO]->(b:Address) WHERE NOT a:Pool AND f.first_seen_timestamp <= 1790812799000 AND f.last_seen_timestamp >= 1788220800000
389
+ RETURN a.address AS from_address, b.address AS to_address, 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, a.labels AS from_labels, b.labels AS to_labels, a.is_exchange AS from_is_exchange, b.is_exchange AS to_is_exchange ORDER BY f.last_seen_timestamp DESC LIMIT 50
390
+ ```
391
+
353
392
  ## Chain: one key, one node
354
393
 
355
394
  `USE chain` asks the chain node for one known thing: `Transaction` by `tx_id`, `Block` by `block_height` or `block_hash` (exactly one), `Address` by `address` (with an optional `at_block`), or `Head`. One node, literal keys in braces, a `RETURN` of `var.property` items, no `WHERE`, no range. `RETURN t` of the whole node is refused (`chain_not_a_lookup`), and a property outside the node's list is refused (`chain_not_served`): a `Transaction` has `tx_id`, `status`, `block_height`, `block_hash`, `tx_index`, `block_timestamp`, `block_date`, `from_address`, `to_address`, `created_contract`, `value`, `nonce`, `gas_used`, `effective_gas_price`, `log_count` and `tx_type`, and no `type`. Read its limits in `chain_admission` (`cia network robinhood --json`).