Skip to content

Officialhomie/balance-tracker

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

balance-tracker

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.

What you need

  • Go 1.22+
  • An RPC URL (local geth, Ankr, Infura, Alchemy, etc.)

Build

go build -o balance-tracker ./cmd/balance-tracker

Usage

Head mode (scan backward from the chain head):

./balance-tracker --address 0xYourAddress --rpc-url https://... --tokens 0xTokenContract --limit 100

Explicit block range (inclusive; both flags required):

./balance-tracker --address 0xYourAddress --rpc-url https://... --from-block 18000000 --to-block 18000100

Flags

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).

Architecture

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 balance vs token balance

  • ETH is returned in wei (smallest unit). The node gives a *big.Int so 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).

Why math/big / *big.Int

Wei and token base units can be far larger than uint64. Go’s math/big gives arbitrary-precision integers so balances stay exact.

How “recent transaction history” works

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 to field matches the address (e.g. incoming ETH).

“Recent” means exactly the blocks you requested: either the last --limit blocks before head, or --from-blockto-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.

Regenerate ERC-20 bindings

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.)

Tests

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).

Risks & tradeoffs

  • 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 shows from as unknown while still matching on to when applicable.

Possible upgrades (not implemented)

  • Efficiency: FilterLogs on Transfer events for token-centric history.
  • Full history: The Graph, a custom indexer (e.g. Postgres), or third-party APIs (Etherscan, Alchemy).

About

CLI: ETH & ERC-20 balances and recent txs via JSON-RPC

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages