Derive Ethereum and Solana addresses from BIP39 seed phrases, then scan for native balances, ERC-20/SPL token holdings, and potential airdrops using the Alchemy API.
- Multichain scanning -- Ethereum (BIP44 coin type 60) and Solana (coin type 501) from a single seed phrase
- Airdrop detection -- Identifies likely airdropped tokens via transfer history analysis
- Alchemy API integration -- Unified API client for both chains with shared CU-aware rate limiting
- Token scanning -- ERC-20 and SPL token balance discovery (including zero-native-balance wallets)
- Spam filtering -- Flags known spam token patterns (URL-in-name, phishing tokens)
- Gap-limit algorithm -- Smart address pruning per chain with token-aware "used" detection
- Flexible export -- CSV and Excel output with chain-colored rows, hyperlinks, and airdrop reports
- Config migration -- Auto-migrates legacy ETH-only config to the new multichain format
pip install -r requirements.txtCopy the example environment file and add your Alchemy API key:
cp .env.example .env
# Edit .env and set ALCHEMY_API_KEYGet a free key at dashboard.alchemy.com.
# Scan a single seed phrase on all chains
python -m app.main --seed "word1 word2 ... word12"
# Scan from a file (one seed phrase per line)
python -m app.main --seed-file seeds.txt
# Ethereum only, CSV output
python -m app.main --seed-file seeds.txt --chain ethereum --format csv
# Disable airdrop detection (faster)
python -m app.main --seed-file seeds.txt --no-detect-airdrops
# Verbose logging
python -m app.main --seed-file seeds.txt -v| Flag | Default | Description |
|---|---|---|
--seed |
-- | Single BIP39 seed phrase (in quotes) |
--seed-file |
-- | Path to file with seed phrases (one per line) |
--chain |
all |
ethereum, solana, or all |
--detect-airdrops / --no-detect-airdrops |
on | Enable/disable airdrop detection |
--tokens / --no-tokens |
on | Enable/disable token balance scanning |
--format |
from config | csv, xlsx, or both |
--output |
from config | Output file path (without extension) |
--config |
config/config.json |
Path to config file |
-v / --verbose |
off | DEBUG-level logging |
app/
__init__.py # v0.3.0
main.py # CLI entry point (click-based)
wallet.py # ETH BIP44 key derivation (eth-account)
solana_wallet.py # SOL BIP44 key derivation (bip_utils)
api.py # Etherscan API wrapper (deprecated, backward compat)
alchemy_api.py # Unified Alchemy client (ETH + SOL, CU rate limiter)
airdrop_detector.py # Airdrop classification engine
scan.py # Multichain scan orchestrator
output_utils.py # CSV/Excel export with chain coloring
config.py # Config loader with legacy migration
logger.py # Dual file + console logger
config/
config.json # Default configuration
tests/
test_config.py # Config validation + migration tests
test_solana_wallet.py # Solana derivation with known test vectors
test_alchemy_api.py # Mocked Alchemy API tests
test_airdrop_detector.py # Airdrop classification tests
test_scan.py # Multichain scan integration tests
The config file (config/config.json) supports per-chain settings:
{
"api_keys": {
"alchemy": "",
"etherscan": ""
},
"chains": {
"ethereum": {
"enabled": true,
"derivation_paths": ["m/44'/60'/0'/0/x"],
"scan_tokens": true
},
"solana": {
"enabled": true,
"derivation_paths": ["m/44'/501'/x'/0'", "m/44'/501'/x'"],
"scan_tokens": true
}
},
"scan_settings": {
"gap_limit": 20,
"batch_size": 5,
"detect_airdrops": true
}
}API keys can also be set via environment variables (ALCHEMY_API_KEY, ETHERSCAN_API_KEY), which take priority over the config file.
- 0 ETH/SOL with tokens: Addresses holding airdropped ERC-20/SPL tokens but 0 native balance are correctly marked as "used" and included in results
- Spam token filtering: Tokens with URL-laden names, phishing patterns, or suspicious symbols are flagged as "spam"
- Shared CU rate limiter: A single rate limiter tracks Alchemy Compute Units across both ETH and SOL chains to stay within the 330 CU/s free tier
- Token metadata caching: Contract metadata (name, symbol, decimals) is cached in-memory to avoid repeated API lookups across addresses
- Config migration: Legacy ETH-only config files are automatically detected and migrated to the multichain format
- Gap limit with tokens: The gap-limit algorithm considers token holdings (not just native balance/tx count) when determining if an address is "used"
pytest tests/ -vMIT License - see LICENSE for details.