--- name: cross-explorer description: This skill should be used when the user asks to look up on-chain data on CROSS Chain — block, transaction, address, contract, or token info — by driving the Blockscout v2 API at https://www.crossscan.io (mainnet 612055) and https://testnet.crossscan.io (testnet 612044) and emitting deep links into the explorer.crosstoken.io UI. Its supported surface is explorer data retrieval only, implemented with zero runtime dependencies. Triggers on phrases like "CROSS 체인 익스플로러", "크로쓰 트랜잭션 조회", "주소 잔액 조회", "최근 블록", "스캔 가스 가격", "CROSS chain explorer", "look up tx on crossscan", "address balance on CROSS", "decode tx logs", "fetch verified source", "search on crossscan". version: 0.1.0 license: MIT --- # CROSS Chain Explorer > **Supported surface:** explorer data lookup only. A distributable skill that lets Claude drive the CROSS Chain block-explorer surface — the **Blockscout v2 API** hosted at `https://www.crossscan.io` (mainnet, chainId `612055`) and `https://testnet.crossscan.io` (testnet, chainId `612044`), with deep links into the `https://explorer.crosstoken.io` UI. Execution is **plain HTTPS GET/POST** via Node's built-in `fetch` — no signer, no `viem`, no browser automation, **zero npm dependencies**. > **Scope (v0.1):** read-only only. Nine subcommands cover the entire user-facing explorer surface — chain stats, latest blocks/txs, block detail, tx detail (with optional log/transfer/internal/state expansion), address profile, verified-contract source, ERC-20/721/1155 token metadata, free-form search, and a deterministic offline URL parser. Every script emits a single JSON envelope on stdout; no decorative prose. > > Deeper protocol details (chain registry, Blockscout v2 endpoint surface, fixture hashes, rate-limit measurements, derivation provenance) live in `references/cross-explorer.md`. Read it only when needed — it stays out of context otherwise. --- ## 1. Activation Activate when the user wants to: - **Read** chain-wide stats (gas prices, total blocks, total transactions, total addresses, transactions today) - Pull the **latest blocks + transactions** (front-page feed; default 6 of each) - Fetch a **block** by height or hash, optionally with the in-block transaction list - Inspect a **transaction** — receipt + value + fee + sender + recipient — and optionally expand `logs`, `token-transfers`, `internal-transactions`, or `state-changes` - Profile an **address** — coin balance, contract flag, verified flag, optional counters / transactions / token-balances - Pull the **verified source** of a contract (ABI + Solidity source, with a 100 KB inline cap) - Resolve **token** metadata (name / symbol / decimals / type / total supply / holders count) for ERC-20, ERC-721, ERC-1155, optionally with `--holders` or `--transfers` listings - Run a **free-form search** through the Blockscout typed search index - Parse a pasted `explorer.crosstoken.io/{chainId}/...` or `crossscan.io/...` URL into `{network, chainId, kind, id}` **offline** (no network call), so a downstream subcommand can be picked deterministically ### Trigger phrases Korean (≥ 6): - `"CROSS 체인 익스플로러"` / `"크로쓰 익스플로러 열어줘"` - `"크로쓰 트랜잭션 조회"` / `"트랜잭션 0x... 분석"` - `"블록 정보 알려줘"` / `"최근 블록 보여줘"` - `"주소 잔액 조회"` / `"이 주소 트랜잭션 목록"` - `"스캔 가스 가격"` / `"체인 통계"` - `"컨트랙트 검증된 소스"` / `"verified source 보여줘"` - `"토큰 홀더 목록"` / `"ERC20 메타데이터"` - `"크로쓰 검색"` / `"crossscan 에서 검색"` English (≥ 6): - `"CROSS chain explorer"` / `"open crossscan for CROSS"` - `"look up tx on crossscan"` / `"decode tx logs"` - `"address balance on CROSS"` / `"recent transactions for 0x..."` - `"block info"` / `"recent blocks"` / `"latest blocks and transactions"` - `"chain stats"` / `"gas price on CROSS chain"` - `"fetch verified source"` / `"contract ABI on crossscan"` - `"token metadata"` / `"token holders list"` - `"search on crossscan"` / `"resolve this explorer URL"` ### URL-paste fast path When the user pastes a URL whose host is `explorer.crosstoken.io`, `www.crossscan.io`, `crossscan.io`, or `testnet.crossscan.io`, **always run `parse-url.mjs` first**. It is offline and deterministic; the resulting `{network, kind, id}` decides which downstream subcommand to invoke (`tx | block | address | token`). Examples: - `https://explorer.crosstoken.io/612055/tx/0xb4faf72fd...` → `tx.mjs 0xb4faf72fd...` - `https://explorer.crosstoken.io/612055/block/32388665` → `block.mjs 32388665` - `https://www.crossscan.io/address/0x0A57…aecD` → `address.mjs 0x0A57…aecD` - `https://testnet.crossscan.io/token/0x1c37…a85C` → `token.mjs --network testnet 0x1c37…a85C` --- ## 2. Prerequisites — verify before doing anything else Run this check first. Stop and report on the first failure. ```bash node --version # require >= 20 (uses built-in fetch + WHATWG URL) ``` `npm install` is **not required** — the skill ships **zero runtime dependencies** (`package.json#dependencies` is `{}`). The `install.sh` wrapper does run `npm install --silent` for parity with sibling skills, but it is a no-op and a failure there does not block any subcommand. ```bash SKILL_DIR="$HOME/.claude/skills/cross-explorer" [ -d "$SKILL_DIR" ] || { echo "skill not installed; run install.sh"; exit 1; } ``` --- ## 3. Credential resolution — **none required** This read-only skill has no signing path, no wallet execution path, and no credential input. There is no wallet-address setup step and `.env.example` deliberately omits credential placeholders. The only env vars the skill ever touches: | Variable | Default | Purpose | |---|---|---| | `EXPLORER_NETWORK` | `mainnet` | Selects `mainnet` (612055) or `testnet` (612044) | | `MAINNET_BASE_URL` | `https://www.crossscan.io` | Override for self-hosted Blockscout mainnet mirror | | `TESTNET_BASE_URL` | `https://testnet.crossscan.io` | Override for self-hosted Blockscout testnet mirror | | `DEBUG` | unset | Set to `1` for verbose stderr; stdout stays a clean JSON envelope | If a caller supplies unrelated wallet secret env vars to a script in this skill, the script silently ignores them. There is no code path that reads wallet secrets. --- ## 4. Execution All subcommands run via Bash and emit a **single JSON envelope on stdout** (no decorative prose). Parse the envelope and report the relevant fields back. Stderr stays empty unless `DEBUG=1`. ```bash cd "$HOME/.claude/skills/cross-explorer" node scripts/.mjs [args...] [--network mainnet|testnet] ``` All scripts accept `--network mainnet|testnet` to override `EXPLORER_NETWORK`. The resolved `{network, chainId, baseUrl}` is echoed in every envelope (success or error) so the caller can never confuse mainnet vs testnet results. ### NL → subcommand map | User says (KR / EN) | Subcommand | |---|---| | "체인 통계" / "stats on CROSS" | `node scripts/stats.mjs` | | "최근 블록 / 트랜잭션" / "latest blocks and txs" | `node scripts/latest.mjs` | | "블록 32388665" / "block 32388665" | `node scripts/block.mjs 32388665` | | "블록 32388665 + 트랜잭션 목록" / "block 32388665 with txs" | `node scripts/block.mjs 32388665 --with-txs` | | "트랜잭션 0xb4faf...72fd" / "tx 0xb4faf...72fd" | `node scripts/tx.mjs 0xb4faf72fd...` | | "트랜잭션 로그 디코드" / "decode tx logs" | `node scripts/tx.mjs 0xb4faf72fd... --include logs,transfers` | | "주소 0x0A57…aecD" / "address 0x0A57…aecD" | `node scripts/address.mjs 0x0A57aecD --counters` | | "주소 트랜잭션" / "address recent txs" | `node scripts/address.mjs 0x0A57…aecD --txs 25` | | "컨트랙트 verified source" / "contract source" | `node scripts/contract.mjs 0x0A57…aecD` | | "토큰 메타데이터" / "token info" | `node scripts/token.mjs 0x1c37…a85C` | | "토큰 홀더" / "token holders" | `node scripts/token.mjs 0x1c37…a85C --holders` | | "검색 USDT" / "search USDT" | `node scripts/search.mjs USDT` | | "이 URL 분석해줘" / "parse this explorer URL" | `node scripts/parse-url.mjs ` | ### Subcommand reference Each block ships with at least one runnable example using mainnet fixtures verified in Phase 1 (see `references/cross-explorer.md`). #### `stats` — chain-wide statistics `GET /api/v2/stats`. Read-only. ```bash node scripts/stats.mjs node scripts/stats.mjs --network testnet ``` Returns `summary.{averageBlockTime, gasPrices.{slow,average,fast}, totalBlocks, totalTransactions, transactionsToday, totalAddresses, gasUsedToday}` plus a `health` block (`{status:"ok"}` or `{status:"degraded", reason}`). #### `latest` — front-page feed `GET /api/v2/main-page/blocks` + `GET /api/v2/main-page/transactions` in parallel. Default 6 of each (cap 6). ```bash node scripts/latest.mjs node scripts/latest.mjs --limit 6 ``` Returns `summary.{blocks[], transactions[]}` with per-row `explorerLink` deep links into `explorer.crosstoken.io`. #### `block` — block detail `GET /api/v2/blocks/{heightOrHash}`. Accepts decimal height (`32388665`), 0x-hex height (`0x1ee9b39`), or 32-byte hash. With `--with-txs`, also pulls `/api/v2/blocks/{id}/transactions` (capped at 50). ```bash node scripts/block.mjs 32388665 node scripts/block.mjs 32388665 --with-txs ``` Returns `summary.{height, hash, timestamp, transactionsCount, gasUsed, gasLimit, miner}`. #### `tx` — transaction detail `GET /api/v2/transactions/{hash}`. With `--include logs,transfers,internal,state` (any subset, comma-separated), expands the corresponding sub-resource. ```bash node scripts/tx.mjs 0xb4faf72fd... node scripts/tx.mjs 0xb4faf72fd... --include logs,transfers node scripts/tx.mjs 0xb4faf72fd... --include logs,transfers,internal,state ``` Returns `summary.{hash, status, blockNumber, from, to, valueWei, valueHuman, gasUsed, feeWei}` plus an `includes` map for each requested expansion. #### `address` — address profile `GET /api/v2/addresses/{addr}`. Optional sidecar fetches: - `--counters` → `/addresses/{addr}/counters` - `--txs N` → `/addresses/{addr}/transactions` (cap N ≤ 200; default 25) - `--filter to|from` → narrows the tx feed - `--tokens` → `/addresses/{addr}/token-balances` ```bash node scripts/address.mjs 0x0A57aecD --counters node scripts/address.mjs 0x0A57aecD --txs 25 --filter to node scripts/address.mjs 0x0A57aecD --tokens ``` Returns `summary.{hash, coinBalanceWei, isContract, isVerified, name, creatorAddressHash, creationTransactionHash}` plus optional `counters`, `transactions[]`, `tokens[]`. #### `contract` — verified-contract source + ABI `GET /api/v2/smart-contracts/{addr}`. **404 → `not_verified`** (frozen error code; treat as "EOA or unverified contract — try `address` instead"). `source_code` is capped at 100 KB inline; the full body still appears under `raw` when smaller, otherwise `truncated:true` with `truncationReason`. ```bash node scripts/contract.mjs 0x0A57aecD ``` Returns `summary.{address, name, compilerVersion, optimizationEnabled, evmVersion, licenseType, abi, sourceCode}`. #### `token` — ERC-20/721/1155 metadata `GET /api/v2/tokens/{addr}`. **404 → `not_a_token`**. Optional sidecars: - `--holders [N]` → `/tokens/{addr}/holders` (cap N ≤ 200; default 25) - `--transfers [N]` → `/tokens/{addr}/transfers` (cap N ≤ 200; default 25) ```bash node scripts/token.mjs 0x1c37a85C node scripts/token.mjs 0x1c37a85C --holders --transfers ``` Returns `summary.{address, name, symbol, decimals, type, totalSupply, holdersCount}`. #### `search` — free-form Blockscout search `GET /api/v2/search?q=…`. Returns the typed item list (each item has a `.type` ∈ `{token, address, block, transaction, label, metadata_tag, contract}`); the script attaches an `explorerLink` to each item that maps to a known kind. ```bash node scripts/search.mjs USDT node scripts/search.mjs 0x0A57aecD ``` Returns `summary.{q, count, kinds[]}` plus `results[]`. #### `parse-url` — offline URL classifier **No network call.** Classifies a pasted URL into `{network, chainId, kind, id}` so a downstream subcommand can be selected deterministically. Accepts `explorer.crosstoken.io/{chainId}/{kind}/{id}`, `https://www.crossscan.io/{kind}/{id}` (mainnet), or `https://testnet.crossscan.io/{kind}/{id}` (testnet implied). ```bash node scripts/parse-url.mjs https://explorer.crosstoken.io/612055/tx/0xb4faf72fd... node scripts/parse-url.mjs https://www.crossscan.io/block/32388665 ``` Bad URLs exit 2 with `{ok:false, error:"bad_url", hint:"..."}`. --- ## 5. Output envelope contract Every successful response **MUST** match this shape: ```json { "ok": true, "command": "tx", "network": "mainnet", "chainId": 612055, "baseUrl": "https://www.crossscan.io", "explorerLink": "https://explorer.crosstoken.io/612055/tx/0xb4faf...", "summary": { /* curated flat fields per command */ }, "raw": { /* upstream Blockscout v2 body, unchanged */ }, "truncated": false, "fetchedAt": "2026-05-04T02:30:00.000Z" } ``` Errors **MUST** match this shape: ```json { "ok": false, "command": "tx", "error": "bad_input", "hint": "expected 0x-prefixed 32-byte hash", "network": "mainnet", "chainId": 612055, "baseUrl": "https://www.crossscan.io", "fetchedAt": "2026-05-04T02:30:00.000Z" } ``` Exit codes: - `0` — success (`ok:true`) - `2` — handled error (any frozen error code other than `rate_limited`) - `4` — `rate_limited` after retries `raw` echoes the upstream body unchanged so the caller can dig into fields the curated `summary` does not surface. `raw_input` (the giant calldata blob on tx detail) is dropped from `raw` to keep envelopes under the 2 MB budget; when that drop or any other byte cap fires, `truncated:true` with `truncationReason`. --- ## 6. Frozen error codes (v0.1) These codes are **frozen** for v0.1. New codes may be added in later versions, but existing ones must not be repurposed. | Code | Meaning | Typical cause | |---|---|---| | `bad_input` | CLI argument failed validation | Missing hash / address / height; bad `--network`; cap exceeded | | `bad_url` | `parse-url` could not classify the URL | Unknown host, missing path segments, non-numeric chainId | | `not_found` | Upstream returned 404 for a generic resource | Unknown block height / tx hash | | `not_verified` | Contract endpoint returned 404 | Address is an EOA or an unverified contract — try `address` instead | | `not_a_token` | Token endpoint returned 404 | Address is an EOA or non-token contract — try `address` instead | | `rate_limited` | 429 after retries | Burst exceeded upstream quota; envelope carries `retry_after_seconds` | | `page_too_large` | Caller asked for more rows than the cap | Use `--holders 200` / `--transfers 200` / `--txs 200` ceilings | | `upstream_error` | 5xx or generic upstream failure | Blockscout outage, network blip; envelope carries `upstreamStatus` and `upstreamBody` (truncated) | | `timeout` | Local 10 s timeout fired | Slow upstream; safe to retry once | --- ## 7. Network selector behavior `--network` precedence (highest wins): 1. `--network mainnet` or `--network=mainnet` on the command line 2. `EXPLORER_NETWORK` env var 3. Default `mainnet` Resolution: | Network | chainId | API base (default) | Override env | UI host | |---|---|---|---|---| | `mainnet` | `612055` | `https://www.crossscan.io` | `MAINNET_BASE_URL` | `https://explorer.crosstoken.io` | | `testnet` | `612044` | `https://testnet.crossscan.io` | `TESTNET_BASE_URL` | `https://explorer.crosstoken.io` | **Guarantee:** every envelope (success or error) echoes `{network, chainId, baseUrl}`. Mixing networks across calls inside one envelope is forbidden; the caller is responsible for keeping the `--network` flag consistent across a multi-step task. --- ## 8. Reference docs Deeper protocol details — chain registry, Blockscout v2 endpoint surface (every endpoint with empirical status code), pagination cursor shape, fixture hashes (block 32388665, tx 0xb4faf...72fd, contract 0x0A57…aecD, token 0x1c37…a85C), rate-limit measurements, derivation provenance — live in `references/cross-explorer.md`. Lazy-load it only when an endpoint returns an unfamiliar shape or you are extending the scripts. The companion design docs (PLAN, REQUIREMENTS, RISKS, ARCHITECTURE) live under the repo's top-level `docs/` directory. --- ## 9. Distribution This skill folder is the unit of distribution. Recipients: 1. Copy the whole `cross-explorer/` folder into `~/.claude/skills/`, **or** run `bash install.sh` from the repo root to symlink it. 2. **No `npm install` required** — `dependencies` is `{}`. The wrapper still runs `npm install --silent` for toolchain parity; failures there are non-fatal. 3. **No `.env` required** — read-only skill, no credentials. The optional `.env.example` only documents the network selector and base-URL overrides. 4. Try it from Claude Code: - `"chain stats on CROSS"` - `"block 32388665 with txs"` - `"resolve this URL: https://explorer.crosstoken.io/612055/tx/0x..."` Cross-link: deeper details live in `references/cross-explorer.md`. Lazy-load on demand.