Small layered CLI that talks to an Ethereum JSON-RPC node: it prints an account’s ETH balance (wei + ETH), optional ERC-20 balances using abigen-generated contract bindings, and recent transactions that touch the address by scanning a limited block range.
This tool scans recent blocks directly via RPC. On mainnet, large scan ranges are slow and may hit provider rate limits. For demonstration, use a local node, a testnet, or a small scan window.
- Go 1.22+
- An RPC URL (local
geth, Ankr, Infura, Alchemy, etc.)
go build -o balance-tracker ./cmd/balance-trackerHead mode (scan backward from the chain head):
./balance-tracker --address 0xYourAddress --rpc-url https://... --tokens 0xTokenContract --limit 100Explicit block range (inclusive; both flags required):
./balance-tracker --address 0xYourAddress --rpc-url https://... --from-block 18000000 --to-block 18000100| Flag | Description |
|---|---|
--address |
Ethereum account (required). Invalid addresses are rejected. |
--rpc-url |
JSON-RPC URL, HTTP or WebSocket (required). |
--tokens |
Optional ERC-20 contract addresses (repeat --tokens or comma-separated in one value). |
--limit |
Blocks to scan backward from head when not using --from-block/--to-block. Default 100, maximum 2000. |
--from-block / --to-block |
Inclusive range; must be used together. Maximum span 2000 blocks. |
--timeout |
RPC deadline for the whole run (default 60s). |
The code is split so the CLI stays thin and logic is testable:
| Package | Role |
|---|---|
cmd/ |
Cobra: flags, validation wiring, orchestration. |
internal/rpc/ |
ethclient.DialContext. |
internal/eth/ |
Native ETH balance via BalanceAt (wei as *big.Int). |
internal/token/ |
ERC-20 via generated bindings in internal/token/erc20/. |
internal/history/ |
Concurrent block fetch (worker pool), sender recovery, filtering from/to. |
internal/blockrange/ |
Validates limits and computes head-backward windows. |
internal/output/ |
Human-readable formatting and section headers. |
- ETH is returned in wei (smallest unit). The node gives a
*big.Intso values cannot overflow a 64-bit integer. - ERC-20 balances are integers in the token’s base units. The human-readable amount divides by
10^decimals(fetched from the contract). Different tokens use different decimals (often 18, but not always).
Wei and token base units can be far larger than uint64. Go’s math/big gives arbitrary-precision integers so balances stay exact.
Ethereum JSON-RPC does not offer “give me all txs for this address.” This tool infers activity by loading blocks in a window and keeping transactions where:
- the recovered sender matches the address, or
- the explicit
tofield matches the address (e.g. incoming ETH).
“Recent” means exactly the blocks you requested: either the last --limit blocks before head, or --from-block–to-block (inclusive). Anything older is simply not scanned.
Not included: internal transfers, full token transfer history (that would need log filters or an indexer), or contract-creation payouts where your address is not the to field.
From internal/token:
go generate ./...(Uses go run …/abigen@…; generated code is committed so a normal go build does not require abigen on your PATH.)
go test ./...Tests cover address parsing, block-range validation, wei formatting, and history scanning against go-ethereum’s simulated backend (including parity between parallel and sequential scans).
-
Limited block scanning performance
Scanning large block ranges via RPC is slow and may hit rate limits. This tool limits scan size and uses concurrent fetching to improve performance. -
No indexer (incomplete history)
Transaction history is derived by scanning a limited block range only. Full historical data requires an indexing solution such as The Graph or explorer APIs. -
Sender recovery assumptions
Sender addresses are recovered using the chain’s signing rules (ChainID+ latest signer). This depends on correct chain ID detection and may not work on non-standard or forked networks. If recovery fails for a transaction, the UI showsfromasunknownwhile still matching ontowhen applicable.
- Efficiency:
FilterLogsonTransferevents for token-centric history. - Full history: The Graph, a custom indexer (e.g. Postgres), or third-party APIs (Etherscan, Alchemy).