{"name":"explore-chain","title":"Explore a chain, with proofs","category":"Prove","summary":"Blocks, transactions, receipts, logs, account scans and protocol transitions, each answer tied to the superroot.","use_when":"You need explorer reads (a tx, an account's events, a protocol's history) and proof that they are inside the root.","not_when":"You need to write, call a contract view, or post a proof to the on-chain verifier.","description":"Use the Taifoon API like any block explorer, with a proof on every answer: look up a block, a transaction or a receipt (GET /v1/chain/{chain}/block|tx|tx/{hash}/receipt), read logs like eth_getLogs (/v1/chain/{chain}/logs), scan an account for the events and transactions that name it (/v1/chain/{chain}/address/{addr}/events|txs), and follow a protocol's state transitions (/v1/transitions/{protocol}). Answers come from the layer's own indexes (held block headers and their blooms, block trees, the superroot, protocol trees); each says source indexed or fetched and carries proof.verified. Use when an agent must find what happened on chain and show it is inside the superroot. Do NOT use to send transactions, to read contract state with eth_call (use rent-rpc), or for the on-chain verifier calldata of one log (use prove-anything).","license":"TSUL","compatibility":"bash, curl, jq; Taifoon coordination API v1 at https://coord.taifoon.dev/v1; a free key (POST /v1/register) for the higher rate","first_call":"GET /v1/chain/{chain}/tx/{hash}","success":"a transaction, an account scan on three chains and an order's transitions answered with proof.verified true","verified":"2026-10-04","hash":"sha256:35bc509779ae1427b9a733c0a9c0401e249e94a01d4eef99de1c3e754cf6a7be","commands":{"ok":true,"blocks":7,"ran_at":"2026-10-04T12:51:47.357Z"},"urls":{"page":"https://www.taifoon.io/skills/explore-chain","markdown":"https://www.taifoon.io/skills/explore-chain.md","json":"https://www.taifoon.io/skills/explore-chain.json","well_known":"https://www.taifoon.io/.well-known/skills/explore-chain/SKILL.md","github":"https://github.com/taifoon-io/skills/tree/main/explore-chain"},"install":{"cli":"npx skills add https://www.taifoon.io --skill explore-chain","curl":"curl -sL https://www.taifoon.io/skills/explore-chain.md"},"markdown":"---\nname: explore-chain\ndescription: \"Use the Taifoon API like any block explorer, with a proof on every answer: look up a block, a transaction or a receipt (GET /v1/chain/{chain}/block|tx|tx/{hash}/receipt), read logs like eth_getLogs (/v1/chain/{chain}/logs), scan an account for the events and transactions that name it (/v1/chain/{chain}/address/{addr}/events|txs), and follow a protocol's state transitions (/v1/transitions/{protocol}). Answers come from the layer's own indexes (held block headers and their blooms, block trees, the superroot, protocol trees); each says source indexed or fetched and carries proof.verified. Use when an agent must find what happened on chain and show it is inside the superroot. Do NOT use to send transactions, to read contract state with eth_call (use rent-rpc), or for the on-chain verifier calldata of one log (use prove-anything).\"\nlicense: TSUL\ncompatibility: \"bash, curl, jq; Taifoon coordination API v1 at https://coord.taifoon.dev/v1; a free key (POST /v1/register) for the higher rate\"\nmetadata:\n  title: \"Explore a chain, with proofs\"\n  category: \"Prove\"\n  summary: \"Blocks, transactions, receipts, logs, account scans and protocol transitions, each answer tied to the superroot.\"\n  use_when: \"You need explorer reads (a tx, an account's events, a protocol's history) and proof that they are inside the root.\"\n  not_when: \"You need to write, call a contract view, or post a proof to the on-chain verifier.\"\n  first_call: \"GET /v1/chain/{chain}/tx/{hash}\"\n  success: \"a transaction, an account scan on three chains and an order's transitions answered with proof.verified true\"\n  verified: \"2026-10-04\"\n---\n\n# Explore a chain, with proofs\n\n## What this is\n\nThe coordination layer answers explorer reads from what it already holds, instead of walking blocks over a public RPC:\n\n| Read | Call | From |\n|---|---|---|\n| Block | `GET /v1/chain/{chain}/block/{latest\\|finalized\\|number\\|hash}` | the header store (`?txs=1` adds the hashes, read once) |\n| Transaction | `GET /v1/chain/{chain}/tx/{hash}` | kept after the first read; events decoded |\n| Receipt | `GET /v1/chain/{chain}/tx/{hash}/receipt` | the same; each log links its inclusion proof |\n| Logs | `GET /v1/chain/{chain}/logs?address=&topic0=&from=&to=` | header blooms pick the blocks, only those are read |\n| Account | `GET /v1/chain/{chain}/address/{addr}/events` or `/txs` | the same blooms, for the address as emitter or topic |\n| Transitions | `GET /v1/transitions/{protocol}?key=` | the protocol trees; no chain is read |\n\nEvery answer carries:\n\n- `source`: `indexed` means no RPC call was made. `fetched` means a part was read once from the chain's rotation and kept\n  once final.\n- `cost`: RPC requests, headers checked, bloom candidates, blocks read.\n- `proof`: the block hash is the leaf at index = block number in the chain's block tree, and that tree is the chain's leaf in\n  the superroot. The layer recomputes both before it answers (`verified`). `checks.block_hash_matches` ties a transaction to\n  the hash in its own receipt.\n\n## Before you start\n\n- Reads need no key inside the visitor rate. A free key (`POST https://coord.taifoon.dev/v1/register`) has its own budget.\n- Lookups are decoded reads (0.05 GRID past the free rate). Account scans are scanning reads (0.1 GRID). `GET /v1/access` has the prices.\n\n```sh\nexport TAIFOON=https://coord.taifoon.dev/v1\ntf() { curl -sS -m 90 -H \"X-Taifoon-Client: taifoon-skill-explore-chain\" ${TAIFOON_API_KEY:+-H \"X-API-Key: $TAIFOON_API_KEY\"} \"$@\"; }\n```\n\n## Pitfalls\n\n1. Reading `ok: true` as proven. Read `proof.status`. `proven` means the block is in the tree, the tree is in the\n   superroot, and the block is at or below the finalized head. `not_final` means the same math holds but the block is newer\n   than that head: ask again later. `pending` means it is newer than the tree's tip. `not_held` means it was never collected.\n2. Asking for a whole chain. A logs query needs an address or a topic, and a window over 10,000 blocks becomes a scan job\n   (HTTP 202 with `job.poll`). Page with `next_cursor` instead of widening the window.\n3. Expecting plain native transfers in an account scan. The scan reads logs blooms. A transfer that emitted no log is not\n   in a bloom, so `coverage.sees` says what is covered.\n4. Treating `final: false` as an error. The default window ends at the tree tip, which is newer than the finalized head.\n   Name `to` at or below `block/finalized` for answers that never change.\n5. Guessing an order key. It is `<protocol>:<chain>:<id>`, for example `erc8183:8453:81435`.\n   `GET /v1/protocols/proven` lists the protocols.\n\n## Steps\n\n### 1. Look up a transaction with its proof\n\nA job created on Virtuals ACP v3 (ERC-8183) on Base:\n\n```sh\nTX=0xc32917e9b8dcbe96a51449d446c89b808e7c784737bef83ad58e7f04400b4d95\ntf \"$TAIFOON/chain/8453/tx/$TX\" | jq -e '.tx.status == \"success\" and .proof.status == \"proven\" and .proof.checks.block_hash_matches and (.proof.anchor.superroot | test(\"^0x[0-9a-f]{64}$\"))' >/dev/null\ntf \"$TAIFOON/chain/8453/tx/$TX/receipt\" | jq -e '(.receipt.logs | length) > 0 and (.receipt.logs[0].proof_url | test(\"/v1/proof/log/8453/\"))' >/dev/null\n```\n\n### 2. The finalized block, from the header store\n\n```sh\ntf \"$TAIFOON/chain/8453/block/finalized\" | jq -e '.source == \"indexed\" and .final and .proof.verified and .cost.rpc_calls == 0' >/dev/null\n```\n\n### 3. Scan an account across chains\n\nCircle's CCTP TokenMessengerV2 has the same address on Base, Arbitrum One and Arc. Its events in each chain's newest 2,000 blocks:\n\n```sh\nA=0x28b5a0e9c621a5badaa536219b3a228c8168cf5d\nfor C in 8453 42161 5042; do\n  tf \"$TAIFOON/chain/$C/address/$A/events?limit=5\" | jq -e '.ok and (.coverage.held_headers > 0) and (.cost.headers_checked > 0) and ((.events | length) == 0 or .proof.verified)' >/dev/null\ndone\n```\n\n### 4. Logs like eth_getLogs, paged\n\nUSDC Transfer events on Arc, five rows, then the next page:\n\n```sh\nT=0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef\nP1=$(tf \"$TAIFOON/chain/5042/logs?topic0=$T&limit=5\")\necho \"$P1\" | jq -e '(.logs | length) >= 5 and .logs[0].decoded.event == \"Transfer\" and .proof.verified and (.next_cursor | type == \"number\")' >/dev/null\ntf \"$TAIFOON/chain/5042/logs?topic0=$T&limit=5&cursor=$(echo \"$P1\" | jq -r .next_cursor)\" | jq -e '.logs[0].block_number >= ('\"$(echo \"$P1\" | jq -r .next_cursor)\"')' >/dev/null\n```\n\n### 5. Follow a protocol's transitions\n\nOne order's lifecycle, then the newest transitions of the Across V3 set:\n\n```sh\ntf \"$TAIFOON/transitions/erc8183?key=erc8183:8453:81435\" | jq -e '.current_state == \"Settled\" and ([.transitions[].to_state] | index(\"Funded\") != null) and .proof.verified and .source == \"indexed\"' >/dev/null\ntf \"$TAIFOON/transitions/across_v3?limit=3\" | jq -e '(.transitions | length) == 3 and .proof.checks.history_in_root and .proof.checks.protocol_in_superroot' >/dev/null\n```\n\n## Verify it works\n\nCheck the proof against a second source: the block hash the chain's own receipt names, read through the RPC gateway, equals\nthe hash the proof holds as the leaf of the block tree.\n\n```sh\nLEAF=$(tf \"$TAIFOON/chain/8453/tx/$TX\" | jq -r '.proof.blocks[0].hash')\ncurl -sS -m 60 -X POST https://coord.taifoon.dev/gw/rpc/8453 -H 'content-type: application/json' -H \"X-Taifoon-Client: taifoon-skill-explore-chain\" ${TAIFOON_API_KEY:+-H \"X-API-Key: $TAIFOON_API_KEY\"} \\\n  -d \"{\\\"jsonrpc\\\":\\\"2.0\\\",\\\"id\\\":1,\\\"method\\\":\\\"eth_getTransactionReceipt\\\",\\\"params\\\":[\\\"$TX\\\"]}\" | jq -e --arg h \"$LEAF\" '.result.blockHash == $h' >/dev/null\necho \"explore-chain: a transaction, a block, an account on three chains, logs and transitions, each under the superroot\"\n```\n\nTo recompute the proof yourself, `?proof=full` returns the multiproof. In TypeScript with viem:\n\n```text\nleaf hashes = proof.multiproof.blockTree.leaves (index = block number); multiRoot(blockTree) must equal anchor.chain_root\nkeccak256(encodePacked(uint64 chainId, uint64 tip_block, bytes32 tip_hash, bytes32 chain_root, uint64 twig_count))\n  folded with multiproof.l3_siblings at anchor.chain_index must equal anchor.superroot\n```\n\n## What it costs\n\nInside the free rate, nothing. Past it, a lookup, a logs page or a transition page is a decoded read (0.05 GRID, 0.0005 USDC),\nand an account scan or a scan-job step is a scanning read (0.1 GRID, 0.001 USDC). Each answer's `cost` says how many RPC calls it made.\n\n## Next\n\n- The same as MCP tools: `taifoon_chain_lookup`, `taifoon_chain_logs`, `taifoon_account_scan`, `taifoon_scan_job`,\n  `taifoon_transitions` (`wrap-in-an-agent`).\n- A stock JSON-RPC client with proofs on request: `rent-rpc` (`taifoon_getProof`).\n- The calldata for the on-chain verifier of one log: `prove-anything`.\n"}