feat(skills): merge blockchain/base into blockchain/evm; salvage PR #2010

Salvages the closed PR #2010 (Mibayy's EVM multi-chain skill) and folds the
existing optional-skills/blockchain/base/ skill into it, so we ship one
unified EVM skill instead of two overlapping ones.

Pulled in from base/:
  - 8 missing Base-specific tokens (AERO, DEGEN, TOSHI, BRETT, WELL,
    cbETH, cbBTC, wstETH, rETH) added to KNOWN_TOKENS['base'] —
    base/ had 11, evm/ only had 3 (USDC/DAI/WETH).
  - L1 data-fee pitfall note for rollups (Base, Arbitrum, Optimism, zkSync).
  - Batch-size chunking in rpc_batch (Base RPC caps batches at 10 calls
    per JSON-RPC request; adding more known tokens tripped that limit
    and broke 'wallet --chain base' with a 'list index out of range'
    error). Ported the chunking pattern from base/_rpc_batch_chunk.

Latent bugs found and fixed while smoke-testing the merge:
  - cmd_multichain and cmd_allowance both iterated KNOWN_TOKENS[chain]
    with 'for contract, (symbol, _name) in known.items()' — but the dict
    shape is {symbol: contract_str}, not {addr: (sym, name)}. This raised
    'too many values to unpack (expected 2)' on every non-zero balance.
    Now iterates as 'for symbol, contract in known.items()'.
  - Input validation: added is_valid_address / is_valid_txhash /
    require_address / require_txhash helpers and wired them into
    cmd_wallet, cmd_tx, cmd_token, cmd_activity, cmd_allowance,
    cmd_decode, cmd_contract, cmd_multichain. Fails fast with exit 2
    on malformed input instead of burning an RPC round-trip on garbage.

Documentation:
  - SKILL.md now flags that this skill supersedes optional-skills/blockchain/base.
  - Pitfalls expanded for ENS (single-endpoint dependency on
    ensideas.com), tx decoding (single-endpoint dependency on
    4byte.directory), and rollup L1 fees.
  - Regenerated website/docs/user-guide/skills/optional/blockchain/
    blockchain-evm.md and removed the old blockchain-base.md page;
    catalog updated.

Removed:
  - optional-skills/blockchain/base/SKILL.md
  - optional-skills/blockchain/base/scripts/base_client.py
  - website/docs/user-guide/skills/optional/blockchain/blockchain-base.md

Smoke-tested live against Base mainnet: stats, price, token, wallet
(vitalik.eth — 3.12 ETH + 13.88 USDC + 4.23 DAI + 0.06 WETH on Base)
and allowance (ethereum, 7 unlimited approvals to Uniswap/Permit2).

Original PR #2010 author: Mibayy.
Original base/ skill author: youssefea.
This commit is contained in:
ethernet 2026-05-13 19:46:22 -04:00 committed by Teknium
parent aa1e2edd35
commit e3fc081499
7 changed files with 354 additions and 1521 deletions

View file

@ -1,232 +0,0 @@
---
name: base
description: Query Base (Ethereum L2) blockchain data with USD pricing — wallet balances, token info, transaction details, gas analysis, contract inspection, whale detection, and live network stats. Uses Base RPC + CoinGecko. No API key required.
version: 0.1.0
author: youssefea
license: MIT
platforms: [linux, macos, windows]
metadata:
hermes:
tags: [Base, Blockchain, Crypto, Web3, RPC, DeFi, EVM, L2, Ethereum]
related_skills: []
---
# Base Blockchain Skill
Query Base (Ethereum L2) on-chain data enriched with USD pricing via CoinGecko.
8 commands: wallet portfolio, token info, transactions, gas analysis,
contract inspection, whale detection, network stats, and price lookup.
No API key needed. Uses only Python standard library (urllib, json, argparse).
---
## When to Use
- User asks for a Base wallet balance, token holdings, or portfolio value
- User wants to inspect a specific transaction by hash
- User wants ERC-20 token metadata, price, supply, or market cap
- User wants to understand Base gas costs and L1 data fees
- User wants to inspect a contract (ERC type detection, proxy resolution)
- User wants to find large ETH transfers (whale detection)
- User wants Base network health, gas price, or ETH price
- User asks "what's the price of USDC/AERO/DEGEN/ETH?"
---
## Prerequisites
The helper script uses only Python standard library (urllib, json, argparse).
No external packages required.
Pricing data comes from CoinGecko's free API (no key needed, rate-limited
to ~10-30 requests/minute). For faster lookups, use `--no-prices` flag.
---
## Quick Reference
RPC endpoint (default): https://mainnet.base.org
Override: export BASE_RPC_URL=https://your-private-rpc.com
Helper script path: ~/.hermes/skills/blockchain/base/scripts/base_client.py
```
python3 base_client.py wallet <address> [--limit N] [--all] [--no-prices]
python3 base_client.py tx <hash>
python3 base_client.py token <contract_address>
python3 base_client.py gas
python3 base_client.py contract <address>
python3 base_client.py whales [--min-eth N]
python3 base_client.py stats
python3 base_client.py price <contract_address_or_symbol>
```
---
## Procedure
### 0. Setup Check
```bash
python3 --version
# Optional: set a private RPC for better rate limits
export BASE_RPC_URL="https://mainnet.base.org"
# Confirm connectivity
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```
### 1. Wallet Portfolio
Get ETH balance and ERC-20 token holdings with USD values.
Checks ~15 well-known Base tokens (USDC, WETH, AERO, DEGEN, etc.)
via on-chain `balanceOf` calls. Tokens sorted by value, dust filtered.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
wallet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
```
Flags:
- `--limit N` — show top N tokens (default: 20)
- `--all` — show all tokens, no dust filter, no limit
- `--no-prices` — skip CoinGecko price lookups (faster, RPC-only)
Output includes: ETH balance + USD value, token list with prices sorted
by value, dust count, total portfolio value in USD.
Note: Only checks known tokens. Unknown ERC-20s are not discovered.
Use the `token` command with a specific contract address for any token.
### 2. Transaction Details
Inspect a full transaction by its hash. Shows ETH value transferred,
gas used, fee in ETH/USD, status, and decoded ERC-20/ERC-721 transfers.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
tx 0xabc123...your_tx_hash_here
```
Output: hash, block, from, to, value (ETH + USD), gas price, gas used,
fee, status, contract creation address (if any), token transfers.
### 3. Token Info
Get ERC-20 token metadata: name, symbol, decimals, total supply, price,
market cap, and contract code size.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Output: name, symbol, decimals, total supply, price, market cap.
Reads name/symbol/decimals directly from the contract via eth_call.
### 4. Gas Analysis
Detailed gas analysis with cost estimates for common operations.
Shows current gas price, base fee trends over 10 blocks, block
utilization, and estimated costs for ETH transfers, ERC-20 transfers,
and swaps.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py gas
```
Output: current gas price, base fee, block utilization, 10-block trend,
cost estimates in ETH and USD.
Note: Base is an L2 — actual transaction costs include an L1 data
posting fee that depends on calldata size and L1 gas prices. The
estimates shown are for L2 execution only.
### 5. Contract Inspection
Inspect an address: determine if it's an EOA or contract, detect
ERC-20/ERC-721/ERC-1155 interfaces, resolve EIP-1967 proxy
implementation addresses.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Output: is_contract, code size, ETH balance, detected interfaces
(ERC-20, ERC-721, ERC-1155), ERC-20 metadata, proxy implementation
address.
### 6. Whale Detector
Scan the most recent block for large ETH transfers with USD values.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
whales --min-eth 1.0
```
Note: scans the latest block only — point-in-time snapshot, not historical.
Default threshold is 1.0 ETH (lower than Solana's default since ETH
values are higher).
### 7. Network Stats
Live Base network health: latest block, chain ID, gas price, base fee,
block utilization, transaction count, and ETH price.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```
### 8. Price Lookup
Quick price check for any token by contract address or known symbol.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price ETH
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price USDC
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price AERO
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price DEGEN
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Known symbols: ETH, WETH, USDC, cbETH, AERO, DEGEN, TOSHI, BRETT,
WELL, wstETH, rETH, cbBTC.
---
## Pitfalls
- **CoinGecko rate-limits** — free tier allows ~10-30 requests/minute.
Price lookups use 1 request per token. Use `--no-prices` for speed.
- **Public RPC rate-limits** — Base's public RPC limits requests.
For production use, set BASE_RPC_URL to a private endpoint
(Alchemy, QuickNode, Infura).
- **Wallet shows known tokens only** — unlike Solana, EVM chains have no
built-in "get all tokens" RPC. The wallet command checks ~15 popular
Base tokens via `balanceOf`. Unknown ERC-20s won't appear. Use the
`token` command for any specific contract.
- **Token names read from contract** — if a contract doesn't implement
`name()` or `symbol()`, these fields may be empty. Known tokens have
hardcoded labels as fallback.
- **Gas estimates are L2 only** — Base transaction costs include an L1
data posting fee (depends on calldata size and L1 gas prices). The gas
command estimates L2 execution cost only.
- **Whale detector scans latest block only** — not historical. Results
vary by the moment you query. Default threshold is 1.0 ETH.
- **Proxy detection** — only EIP-1967 proxies are detected. Other proxy
patterns (EIP-1167 minimal proxy, custom storage slots) are not checked.
- **Retry on 429** — both RPC and CoinGecko calls retry up to 2 times
with exponential backoff on rate-limit errors.
---
## Verification
```bash
# Should print Base chain ID (8453), latest block, gas price, and ETH price
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,11 @@ Optimism, Avalanche (C-Chain), zkSync Era.
No API key needed. Zero external dependencies — Python standard library only
(urllib, json, argparse, threading).
> **Supersedes the standalone `base` skill.** Base-specific tokens (AERO, DEGEN,
> TOSHI, BRETT, WELL, cbETH, cbBTC, wstETH, rETH) and all Base RPC functionality
> previously living under `optional-skills/blockchain/base/` have been folded
> into this skill. Pass `--chain base` to any command for Base coverage.
---
## When to Use
@ -188,8 +193,10 @@ Shows gwei price + USD cost for: transfer, ERC-20 transfer, approve, swap, NFT m
- `wallet` and `allowance` only check known token list (~30 tokens per chain). Use a block explorer for complete token discovery.
- `activity` scans recent blocks only (max 200). For full history, use Etherscan API.
- `multichain` runs 8 parallel threads — can trigger rate limits on public RPCs.
- ENS requires internet access to ensideas.com.
- Tx decode requires internet access to 4byte.directory.
- ENS resolution depends on a single public endpoint (ensideas.com / ens.vitalik.ca) with no fallback. If that endpoint is down, `ens` will fail — re-run later or use a block explorer.
- Tx decoding depends on a single public endpoint (4byte.directory) with no fallback. Selectors not in their database show up as `unknown`.
- **L2 gas estimates are L2-execution only.** On rollups like Base, Arbitrum, Optimism, and zkSync, the actual transaction cost also includes an L1 data-posting fee that depends on calldata size and current L1 gas prices. The `gas` command does not estimate that L1 component. For Base specifically, see the network's L1 fee oracle (contract `0x420000000000000000000000000000000000000F`).
- Address / tx-hash inputs are validated for 0x-prefix + correct length + hex, but EIP-55 checksum casing is **not** enforced (RPC endpoints accept any-case hex).
---

View file

@ -137,9 +137,21 @@ KNOWN_TOKENS: Dict[str, Dict[str, str]] = {
"DOGE": "0xbA2aE424d960c26247Dd6c32edC70B295c744C43",
},
"base": {
"USDC": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"DAI": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
"WETH": "0x4200000000000000000000000000000000000006",
# Stables + wrapped
"USDC": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"DAI": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
"WETH": "0x4200000000000000000000000000000000000006",
# Liquid-staked ETH variants
"cbETH": "0x2Ae3F1Ec7F1F5012CFEab0185bfc7aa3cF0DEc22",
"wstETH": "0xc1CBa3fCea344f92D9239c08C0568f6F2F0ee452",
"rETH": "0xB6fe221Fe9EeF5aBa221c348bA20A1Bf5e73624c",
"cbBTC": "0xcbB7C0000aB88B473b1f5aFd9ef808440eed33Bf",
# Base-native DeFi + meme tokens (carried over from the standalone base/ skill)
"AERO": "0x940181a94A35A4569E4529A3CDfB74e38FD98631",
"DEGEN": "0x4ed4E862860beD51a9570b96d89aF5E1B0Efefed",
"TOSHI": "0xAC1Bd2486aAf3B5C0fc3Fd868558b082a531B2B4",
"BRETT": "0x532f27101965dd16442E59d40670FaF5eBB142E4",
"WELL": "0xA88594D404727625A9437C3f886C7643872296AE",
},
"arbitrum": {
"USDC": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
@ -226,9 +238,73 @@ def hex_to_int(h: str) -> int:
return 0
return int(h, 16)
# ---------------------------------------------------------------------------
# Input validation
# ---------------------------------------------------------------------------
def is_valid_address(s: str) -> bool:
"""Return True if `s` looks like a 20-byte hex Ethereum address.
Does NOT validate EIP-55 checksum RPC endpoints accept any-case hex.
Just guards against typos / wrong-length input before we burn an RPC call.
"""
if not isinstance(s, str):
return False
if not s.startswith("0x") and not s.startswith("0X"):
return False
if len(s) != 42:
return False
try:
int(s, 16)
except ValueError:
return False
return True
def is_valid_txhash(s: str) -> bool:
"""Return True if `s` looks like a 32-byte hex transaction hash."""
if not isinstance(s, str):
return False
if not s.startswith("0x") and not s.startswith("0X"):
return False
if len(s) != 66:
return False
try:
int(s, 16)
except ValueError:
return False
return True
def require_address(s: str, *, field: str = "address") -> str:
"""Return `s` lowercased if valid, else exit with an error message.
Centralizing validation here means every subcommand fails fast on bad input
instead of bubbling up an opaque RPC error 30 seconds later.
"""
if not is_valid_address(s):
sys.stderr.write(
f"error: invalid {field} {s!r}: expected 0x-prefixed 40-hex-char address\n"
)
sys.exit(2)
return s.lower()
def require_txhash(s: str, *, field: str = "tx hash") -> str:
"""Return `s` lowercased if valid, else exit with an error message."""
if not is_valid_txhash(s):
sys.stderr.write(
f"error: invalid {field} {s!r}: expected 0x-prefixed 64-hex-char tx hash\n"
)
sys.exit(2)
return s.lower()
def wei_to_native(wei: int, decimals: int = 18) -> float:
return wei / (10 ** decimals)
def gwei_from_wei(wei: int) -> float:
return wei / 1e9
@ -326,25 +402,36 @@ def rpc_call(chain: str, method: str, params: List[Any], req_id: int = 1) -> Any
raise RuntimeError(f"RPC error: {resp['error']}")
return resp.get("result")
def rpc_batch(chain: str, calls: List[Tuple[str, List[Any]]]) -> List[Any]:
"""Send a batch of JSON-RPC calls; returns list of results in same order."""
def rpc_batch(chain: str, calls: List[Tuple[str, List[Any]]], batch_limit: int = 10) -> List[Any]:
"""Send a batch of JSON-RPC calls; returns list of results in same order.
Auto-chunks at `batch_limit` (default 10) so we stay under per-RPC limits.
Base's public RPC caps batches at 10 — exceeding that returns a single error
dict instead of a results list, which would mask all our calls.
"""
url = get_rpc_url(chain)
payload = [
# Build the full payload, preserving order via JSON-RPC `id`
items = [
{"jsonrpc": "2.0", "id": i, "method": m, "params": p}
for i, (m, p) in enumerate(calls)
]
resp = _http_post(url, payload)
if isinstance(resp, list):
# Sort by id to preserve order
resp_sorted = sorted(resp, key=lambda x: x.get("id", 0))
results = []
for r in resp_sorted:
if "error" in r:
results.append(None)
else:
results.append(r.get("result"))
return results
return [resp.get("result")]
out: List[Any] = [None] * len(items)
for start in range(0, len(items), batch_limit):
chunk = items[start:start + batch_limit]
resp = _http_post(url, chunk)
if not isinstance(resp, list):
# Single error response (e.g. batch-too-large) — leave this chunk as None
continue
for r in resp:
rid = r.get("id")
if isinstance(rid, int) and 0 <= rid < len(out):
if "error" in r:
out[rid] = None
else:
out[rid] = r.get("result")
return out
# ---------------------------------------------------------------------------
# ABI encoding helpers (minimal, for ERC-20 calls)
@ -556,7 +643,7 @@ def cmd_stats(args: argparse.Namespace) -> None:
def cmd_wallet(args: argparse.Namespace) -> None:
address = args.address
address = require_address(args.address)
chain = args.chain
limit = args.limit
no_prices = args.no_prices
@ -633,7 +720,7 @@ def cmd_wallet(args: argparse.Namespace) -> None:
def cmd_tx(args: argparse.Namespace) -> None:
tx_hash = args.hash
tx_hash = require_txhash(args.hash)
chain = args.chain
cfg = CHAINS[chain]
@ -702,7 +789,7 @@ def cmd_tx(args: argparse.Namespace) -> None:
def cmd_token(args: argparse.Namespace) -> None:
contract = args.contract
contract = require_address(args.contract, field="contract address")
chain = args.chain
# Batch all ERC-20 metadata calls
@ -744,7 +831,7 @@ def cmd_token(args: argparse.Namespace) -> None:
def cmd_activity(args: argparse.Namespace) -> None:
address = args.address
address = require_address(args.address)
chain = args.chain
limit = args.limit
cfg = CHAINS[chain]
@ -1000,7 +1087,7 @@ def cmd_multichain(args: argparse.Namespace) -> None:
"""Scan same wallet across all 8 chains simultaneously."""
import threading
address = args.address
address = require_address(args.address)
results: Dict[str, Any] = {}
lock = threading.Lock()
@ -1019,9 +1106,10 @@ def cmd_multichain(args: argparse.Namespace) -> None:
"tokens": [],
"total_usd": native_usd or 0.0,
}
# Check known tokens for this chain
# Check known tokens for this chain.
# KNOWN_TOKENS[chain] maps {symbol: contract_address}, not {addr: (sym, name)}.
known = KNOWN_TOKENS.get(chain, {})
for contract, (symbol, _name) in known.items():
for symbol, contract in known.items():
raw = eth_call_erc20(chain, contract, "balanceOf(address)", address)
if not raw or raw == "0x":
continue
@ -1067,7 +1155,7 @@ def cmd_multichain(args: argparse.Namespace) -> None:
def cmd_allowance(args: argparse.Namespace) -> None:
"""Check dangerous ERC-20 approvals for a wallet (known spenders)."""
address = args.address
address = require_address(args.address)
chain = args.chain
# Well-known spender contracts (DEXes, bridges, etc.)
@ -1085,7 +1173,8 @@ def cmd_allowance(args: argparse.Namespace) -> None:
known = KNOWN_TOKENS.get(chain, {})
approvals = []
for contract, (symbol, _name) in known.items():
# KNOWN_TOKENS[chain] is {symbol: contract_address}, not {addr: (sym, name)}.
for symbol, contract in known.items():
for spender_addr, spender_name in KNOWN_SPENDERS.items():
# allowance(owner, spender) = 0xdd62ed3e
owner_pad = address.lower().replace("0x", "").zfill(64)
@ -1127,7 +1216,7 @@ def cmd_allowance(args: argparse.Namespace) -> None:
def cmd_decode(args: argparse.Namespace) -> None:
"""Decode transaction input data using 4byte.directory."""
chain = args.chain
tx_hash = args.hash
tx_hash = require_txhash(args.hash)
tx = rpc_call(chain, "eth_getTransactionByHash", [tx_hash])
if not tx:
@ -1212,7 +1301,7 @@ def cmd_ens(args: argparse.Namespace) -> None:
def cmd_contract(args: argparse.Namespace) -> None:
"""Inspect a smart contract: bytecode size, proxy detection, creation info."""
chain = args.chain
address = args.address
address = require_address(args.address)
# Get bytecode
code_hex = rpc_call(chain, "eth_getCode", [address, "latest"])

View file

@ -38,7 +38,7 @@ hermes skills uninstall <skill-name>
| Skill | Description |
|-------|-------------|
| [**base**](/docs/user-guide/skills/optional/blockchain/blockchain-base) | Query Base (Ethereum L2) blockchain data with USD pricing — wallet balances, token info, transaction details, gas analysis, contract inspection, whale detection, and live network stats. Uses Base RPC + CoinGecko. No API key required. |
| [**evm**](/docs/user-guide/skills/optional/blockchain/blockchain-evm) | Query EVM blockchain data across 8 chains — wallet portfolios, ERC-20 tokens, transactions, gas tracker, whale detection, multi-chain scan, ENS resolution, allowance checker, contract inspection, and tx decoder. Supports Ethereum, BNB Chain, Base, Arbitrum, Polygon, Optimism, Avalanche, zkSync. Uses public RPCs + CoinGecko. No API key required. |
| [**solana**](/docs/user-guide/skills/optional/blockchain/blockchain-solana) | Query Solana blockchain data with USD pricing — wallet balances, token portfolios with values, transaction details, NFTs, whale detection, and live network stats. Uses Solana RPC + CoinGecko. No API key required. |
## communication

View file

@ -1,249 +0,0 @@
---
title: "Base"
sidebar_label: "Base"
description: "Query Base (Ethereum L2) blockchain data with USD pricing — wallet balances, token info, transaction details, gas analysis, contract inspection, whale detect..."
---
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
# Base
Query Base (Ethereum L2) blockchain data with USD pricing — wallet balances, token info, transaction details, gas analysis, contract inspection, whale detection, and live network stats. Uses Base RPC + CoinGecko. No API key required.
## Skill metadata
| | |
|---|---|
| Source | Optional — install with `hermes skills install official/blockchain/base` |
| Path | `optional-skills/blockchain/base` |
| Version | `0.1.0` |
| Author | youssefea |
| License | MIT |
| Platforms | linux, macos, windows |
| Tags | `Base`, `Blockchain`, `Crypto`, `Web3`, `RPC`, `DeFi`, `EVM`, `L2`, `Ethereum` |
## Reference: full SKILL.md
:::info
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
:::
# Base Blockchain Skill
Query Base (Ethereum L2) on-chain data enriched with USD pricing via CoinGecko.
8 commands: wallet portfolio, token info, transactions, gas analysis,
contract inspection, whale detection, network stats, and price lookup.
No API key needed. Uses only Python standard library (urllib, json, argparse).
---
## When to Use
- User asks for a Base wallet balance, token holdings, or portfolio value
- User wants to inspect a specific transaction by hash
- User wants ERC-20 token metadata, price, supply, or market cap
- User wants to understand Base gas costs and L1 data fees
- User wants to inspect a contract (ERC type detection, proxy resolution)
- User wants to find large ETH transfers (whale detection)
- User wants Base network health, gas price, or ETH price
- User asks "what's the price of USDC/AERO/DEGEN/ETH?"
---
## Prerequisites
The helper script uses only Python standard library (urllib, json, argparse).
No external packages required.
Pricing data comes from CoinGecko's free API (no key needed, rate-limited
to ~10-30 requests/minute). For faster lookups, use `--no-prices` flag.
---
## Quick Reference
RPC endpoint (default): https://mainnet.base.org
Override: export BASE_RPC_URL=https://your-private-rpc.com
Helper script path: ~/.hermes/skills/blockchain/base/scripts/base_client.py
```
python3 base_client.py wallet <address> [--limit N] [--all] [--no-prices]
python3 base_client.py tx <hash>
python3 base_client.py token <contract_address>
python3 base_client.py gas
python3 base_client.py contract <address>
python3 base_client.py whales [--min-eth N]
python3 base_client.py stats
python3 base_client.py price <contract_address_or_symbol>
```
---
## Procedure
### 0. Setup Check
```bash
python3 --version
# Optional: set a private RPC for better rate limits
export BASE_RPC_URL="https://mainnet.base.org"
# Confirm connectivity
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```
### 1. Wallet Portfolio
Get ETH balance and ERC-20 token holdings with USD values.
Checks ~15 well-known Base tokens (USDC, WETH, AERO, DEGEN, etc.)
via on-chain `balanceOf` calls. Tokens sorted by value, dust filtered.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
wallet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
```
Flags:
- `--limit N` — show top N tokens (default: 20)
- `--all` — show all tokens, no dust filter, no limit
- `--no-prices` — skip CoinGecko price lookups (faster, RPC-only)
Output includes: ETH balance + USD value, token list with prices sorted
by value, dust count, total portfolio value in USD.
Note: Only checks known tokens. Unknown ERC-20s are not discovered.
Use the `token` command with a specific contract address for any token.
### 2. Transaction Details
Inspect a full transaction by its hash. Shows ETH value transferred,
gas used, fee in ETH/USD, status, and decoded ERC-20/ERC-721 transfers.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
tx 0xabc123...your_tx_hash_here
```
Output: hash, block, from, to, value (ETH + USD), gas price, gas used,
fee, status, contract creation address (if any), token transfers.
### 3. Token Info
Get ERC-20 token metadata: name, symbol, decimals, total supply, price,
market cap, and contract code size.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
token 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Output: name, symbol, decimals, total supply, price, market cap.
Reads name/symbol/decimals directly from the contract via eth_call.
### 4. Gas Analysis
Detailed gas analysis with cost estimates for common operations.
Shows current gas price, base fee trends over 10 blocks, block
utilization, and estimated costs for ETH transfers, ERC-20 transfers,
and swaps.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py gas
```
Output: current gas price, base fee, block utilization, 10-block trend,
cost estimates in ETH and USD.
Note: Base is an L2 — actual transaction costs include an L1 data
posting fee that depends on calldata size and L1 gas prices. The
estimates shown are for L2 execution only.
### 5. Contract Inspection
Inspect an address: determine if it's an EOA or contract, detect
ERC-20/ERC-721/ERC-1155 interfaces, resolve EIP-1967 proxy
implementation addresses.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
contract 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Output: is_contract, code size, ETH balance, detected interfaces
(ERC-20, ERC-721, ERC-1155), ERC-20 metadata, proxy implementation
address.
### 6. Whale Detector
Scan the most recent block for large ETH transfers with USD values.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py \
whales --min-eth 1.0
```
Note: scans the latest block only — point-in-time snapshot, not historical.
Default threshold is 1.0 ETH (lower than Solana's default since ETH
values are higher).
### 7. Network Stats
Live Base network health: latest block, chain ID, gas price, base fee,
block utilization, transaction count, and ETH price.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```
### 8. Price Lookup
Quick price check for any token by contract address or known symbol.
```bash
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price ETH
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price USDC
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price AERO
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price DEGEN
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py price 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913
```
Known symbols: ETH, WETH, USDC, cbETH, AERO, DEGEN, TOSHI, BRETT,
WELL, wstETH, rETH, cbBTC.
---
## Pitfalls
- **CoinGecko rate-limits** — free tier allows ~10-30 requests/minute.
Price lookups use 1 request per token. Use `--no-prices` for speed.
- **Public RPC rate-limits** — Base's public RPC limits requests.
For production use, set BASE_RPC_URL to a private endpoint
(Alchemy, QuickNode, Infura).
- **Wallet shows known tokens only** — unlike Solana, EVM chains have no
built-in "get all tokens" RPC. The wallet command checks ~15 popular
Base tokens via `balanceOf`. Unknown ERC-20s won't appear. Use the
`token` command for any specific contract.
- **Token names read from contract** — if a contract doesn't implement
`name()` or `symbol()`, these fields may be empty. Known tokens have
hardcoded labels as fallback.
- **Gas estimates are L2 only** — Base transaction costs include an L1
data posting fee (depends on calldata size and L1 gas prices). The gas
command estimates L2 execution cost only.
- **Whale detector scans latest block only** — not historical. Results
vary by the moment you query. Default threshold is 1.0 ETH.
- **Proxy detection** — only EIP-1967 proxies are detected. Other proxy
patterns (EIP-1167 minimal proxy, custom storage slots) are not checked.
- **Retry on 429** — both RPC and CoinGecko calls retry up to 2 times
with exponential backoff on rate-limit errors.
---
## Verification
```bash
# Should print Base chain ID (8453), latest block, gas price, and ETH price
python3 ~/.hermes/skills/blockchain/base/scripts/base_client.py stats
```

View file

@ -0,0 +1,226 @@
---
title: "Evm"
sidebar_label: "Evm"
description: "Query EVM blockchain data across 8 chains — wallet portfolios, ERC-20 tokens, transactions, gas tracker, whale detection, multi-chain scan, ENS resolution, a..."
---
{/* This page is auto-generated from the skill's SKILL.md by website/scripts/generate-skill-docs.py. Edit the source SKILL.md, not this page. */}
# Evm
Query EVM blockchain data across 8 chains — wallet portfolios, ERC-20 tokens, transactions, gas tracker, whale detection, multi-chain scan, ENS resolution, allowance checker, contract inspection, and tx decoder. Supports Ethereum, BNB Chain, Base, Arbitrum, Polygon, Optimism, Avalanche, zkSync. Uses public RPCs + CoinGecko. No API key required.
## Skill metadata
| | |
|---|---|
| Source | Optional — install with `hermes skills install official/blockchain/evm` |
| Path | `optional-skills/blockchain/evm` |
| Version | `1.0.0` |
| Author | Mibayy |
| License | MIT |
| Tags | `EVM`, `Ethereum`, `BNB`, `BSC`, `Base`, `Arbitrum`, `Polygon`, `Optimism`, `Avalanche`, `zkSync`, `Blockchain`, `Crypto`, `Web3`, `DeFi`, `NFT`, `ENS`, `Whale`, `Security` |
| Related skills | [`solana`](/docs/user-guide/skills/optional/blockchain/blockchain-solana) |
## Reference: full SKILL.md
:::info
The following is the complete skill definition that Hermes loads when this skill is triggered. This is what the agent sees as instructions when the skill is active.
:::
# EVM Blockchain Skill
Query EVM-compatible blockchain data across 8 chains with USD pricing.
14 commands: wallet portfolio, token info, transactions, activity, gas tracker,
network stats, price lookup, multi-chain scan, whale detection, ENS resolution,
allowance checker, contract inspector, and transaction decoder.
Supports 8 chains: Ethereum, BNB Chain (BSC), Base, Arbitrum One, Polygon,
Optimism, Avalanche (C-Chain), zkSync Era.
No API key needed. Zero external dependencies — Python standard library only
(urllib, json, argparse, threading).
> **Supersedes the standalone `base` skill.** Base-specific tokens (AERO, DEGEN,
> TOSHI, BRETT, WELL, cbETH, cbBTC, wstETH, rETH) and all Base RPC functionality
> previously living under `optional-skills/blockchain/base/` have been folded
> into this skill. Pass `--chain base` to any command for Base coverage.
---
## When to Use
- User asks for a wallet balance or portfolio on any EVM chain
- User wants to check the same wallet across ALL chains at once
- User wants to inspect a transaction by hash (or decode what it did)
- User wants ERC-20 token metadata, price, supply, or market cap
- User wants recent transaction history for an address
- User wants current gas prices or to compare fees across chains
- User wants to find large whale transfers in recent blocks
- User asks to resolve an ENS name (vitalik.eth) or reverse-lookup an address
- User wants to check if a contract has dangerous token approvals
- User wants to inspect a smart contract (proxy? ERC-20? ERC-721? bytecode size?)
- User wants to compare gas costs across chains before a transaction
---
## Prerequisites
Python 3.8+ standard library only. No pip installs required.
Pricing: CoinGecko free API (rate-limited, ~10-30 req/min).
ENS: ensideas.com public API.
Tx decoding: 4byte.directory public API.
Override RPC endpoint: `export EVM_RPC_URL=https://your-rpc.com`
Helper script path: `~/.hermes/skills/blockchain/evm/scripts/evm_client.py`
---
## Quick Reference
```
SCRIPT=~/.hermes/skills/blockchain/evm/scripts/evm_client.py
# Network & prices
python3 $SCRIPT stats # Ethereum stats
python3 $SCRIPT stats --chain arbitrum # Arbitrum stats
python3 $SCRIPT compare # Gas + prices ALL 8 chains
# Wallet
python3 $SCRIPT wallet 0xd8dA...96045 # Portfolio (ETH + ERC-20)
python3 $SCRIPT wallet 0xd8dA...96045 --chain bsc
python3 $SCRIPT multichain 0xd8dA...96045 # Same wallet on ALL chains
# Tokens & prices
python3 $SCRIPT price ETH
python3 $SCRIPT price 0xdAC1...1ec7 # By contract address
python3 $SCRIPT token 0xdAC1...1ec7 # ERC-20 metadata + market cap
# Transactions
python3 $SCRIPT tx 0x5c50...f060 # Transaction details
python3 $SCRIPT decode 0x5c50...f060 # Decode input data (4byte.directory)
python3 $SCRIPT activity 0xd8dA...96045 # Recent transactions
# Gas
python3 $SCRIPT gas # Gas prices + cost estimates
python3 $SCRIPT gas --chain optimism
# Security
python3 $SCRIPT allowance 0xd8dA...96045 # Dangerous ERC-20 approvals
python3 $SCRIPT contract 0xdAC1...1ec7 # Contract inspection (proxy? standards?)
# ENS
python3 $SCRIPT ens vitalik.eth # Name -> address + profile
python3 $SCRIPT ens 0xd8dA...96045 # Address -> ENS name
# Whale detection
python3 $SCRIPT whale # Large transfers (last 20 blocks, >$10k)
python3 $SCRIPT whale --blocks 50 --min-usd 100000 --chain arbitrum
```
---
## Procedure
### 0. Setup Check
```bash
python3 --version # 3.8+ required
python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats
```
### 1. Wallet Portfolio
Native balance + known ERC-20 tokens, sorted by USD value.
```bash
python3 $SCRIPT wallet 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
python3 $SCRIPT wallet 0xd8dA... --chain bsc --no-prices # faster
```
### 2. Multi-Chain Scan
Scans all 8 chains simultaneously for the same address using threads.
```bash
python3 $SCRIPT multichain 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045
```
Output: per-chain native balance + token holdings + grand total USD.
### 3. Compare (Gas + Prices)
All 8 chains queried in parallel. Shows cheapest/most expensive chain.
```bash
python3 $SCRIPT compare
```
### 4. Transaction Details & Decode
```bash
python3 $SCRIPT tx 0x5c504ed432cb51138bcf09aa5e8a410dd4a1e204ef84bfed1be16dfba1b22060
python3 $SCRIPT decode 0x5c504ed... # Shows human-readable function signature
```
Decode uses 4byte.directory to translate 0xa9059cbb -> transfer(address,uint256).
### 5. ENS Resolution
```bash
python3 $SCRIPT ens vitalik.eth # -> 0xd8dA... + avatar + social links
python3 $SCRIPT ens 0xd8dA...96045 # -> vitalik.eth
```
### 6. Allowance Checker (Security)
Checks ERC-20 approvals granted to known DEX/bridge contracts.
```bash
python3 $SCRIPT allowance 0xYourWallet
```
Flags UNLIMITED approvals as HIGH risk.
### 7. Contract Inspector
```bash
python3 $SCRIPT contract 0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48 # USDC (proxy)
python3 $SCRIPT contract 0xdAC17F958D2ee523a2206206994597C13D831ec7 # USDT (ERC-20)
```
Detects: proxy (EIP-1967/EIP-1167), ERC-20, ERC-721, ERC-165. Shows bytecode size and implementation address for proxies.
### 8. Whale Detection
```bash
python3 $SCRIPT whale # ETH, last 20 blocks, >$10k
python3 $SCRIPT whale --blocks 50 --min-usd 50000 --chain bsc
```
### 9. Gas Tracker
```bash
python3 $SCRIPT gas
python3 $SCRIPT gas --chain polygon
```
Shows gwei price + USD cost for: transfer, ERC-20 transfer, approve, swap, NFT mint, NFT transfer.
---
## Supported Chains
| Key | Name | Native | Chain ID |
|-----------|----------------|--------|----------|
| ethereum | Ethereum | ETH | 1 |
| bsc | BNB Chain | BNB | 56 |
| base | Base | ETH | 8453 |
| arbitrum | Arbitrum One | ETH | 42161 |
| polygon | Polygon | POL | 137 |
| optimism | Optimism | ETH | 10 |
| avalanche | Avalanche C | AVAX | 43114 |
| zksync | zkSync Era | ETH | 324 |
---
## Pitfalls
- CoinGecko free tier: ~10-30 req/min. Use `--no-prices` for faster wallet scans.
- Public RPCs may throttle. Set EVM_RPC_URL to a private endpoint for production.
- `wallet` and `allowance` only check known token list (~30 tokens per chain). Use a block explorer for complete token discovery.
- `activity` scans recent blocks only (max 200). For full history, use Etherscan API.
- `multichain` runs 8 parallel threads — can trigger rate limits on public RPCs.
- ENS resolution depends on a single public endpoint (ensideas.com / ens.vitalik.ca) with no fallback. If that endpoint is down, `ens` will fail — re-run later or use a block explorer.
- Tx decoding depends on a single public endpoint (4byte.directory) with no fallback. Selectors not in their database show up as `unknown`.
- **L2 gas estimates are L2-execution only.** On rollups like Base, Arbitrum, Optimism, and zkSync, the actual transaction cost also includes an L1 data-posting fee that depends on calldata size and current L1 gas prices. The `gas` command does not estimate that L1 component. For Base specifically, see the network's L1 fee oracle (contract `0x420000000000000000000000000000000000000F`).
- Address / tx-hash inputs are validated for 0x-prefix + correct length + hex, but EIP-55 checksum casing is **not** enforced (RPC endpoints accept any-case hex).
---
## Verification
```bash
# Should print current block, gas price, ETH price
python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py stats
# Should resolve vitalik.eth to 0xd8dA...
python3 ~/.hermes/skills/blockchain/evm/scripts/evm_client.py ens vitalik.eth
```