Introduction
Ethereum wallets can hold ETH, dozens of ERC-20 tokens, and NFTs spread across multiple collections — yet most tools only show you one piece at a time. I set out to fix that by building a Token & NFT Portfolio API: a FastAPI service that aggregates Ethereum wallet balances, fungible tokens, and NFTs into clean, structured JSON responses.
Whether you're building a crypto dashboard, an NFT explorer, a wallet intelligence tool, or an Ethereum analytics platform, this API gives you a single endpoint to query instead of cobbling together multiple providers.
Here's what we built, how it works, and what comes next.
What It Does
The API solves a deceptively simple problem: given a wallet address, return everything that wallet holds — tokens, NFTs, and native balances — in a consistent, developer-friendly format.
That means:
- Ethereum wallet portfolio tracking — query token and NFT holdings for any wallet address
- NFT portfolio retrieval — surface NFT holdings by collection, token ID, and metadata
- Fungible token balance aggregation — aggregate ERC-20 balances for a given wallet
- Clean JSON responses — typed, predictable response shapes that frontend apps can trust
- Auto-generated API docs — Swagger UI and ReDoc ship out of the box with FastAPI
Tech Stack
| Layer | Technology |
|---|---|
| Framework | FastAPI |
| Server | Uvicorn |
| Blockchain data | Web3 APIs |
| HTTP client | httpx (async) |
| Data modeling | Pydantic |
| Auth tokens | python-jose |
| Config | python-dotenv |
| Wallet utilities | web3, eth-account |
| Database (future) | SQLAlchemy + Alembic + PostgreSQL |
Project Structure
The codebase follows a clean separation of concerns — routes own HTTP logic, services own business logic, schemas own data shapes, and utils own helpers.
token-nft_portfolio_api/
│
├── app/
│ ├── main.py
│ ├── routes/
│ ├── services/
│ ├── schemas/
│ └── utils/
│
├── requirements.txt
├── .env # API keys (never committed)
├── .gitignore
└── README.md
This structure scales well. Adding a new feature area means dropping a new service module and wiring up a route — the rest of the app stays untouched.
API Endpoints
GET /portfolio/summary/{wallet_address}
Returns a complete Ethereum portfolio overview for the given wallet — ETH balance, ERC-20 token holdings, and NFTs.
{
"wallet": "0x123...",
"chain": "ethereum",
"tokens": [
{
"symbol": "ETH",
"balance": "1.25"
}
],
"nfts": [
{
"name": "CryptoPunk",
"token_id": "1234"
}
]
}
GET /portfolio/nft/{wallet_address}
Fetches the full NFT holdings for a wallet: collection name, token ID, and available metadata. Useful for building NFT gallery views or ownership verification flows.
GET /wallet/balance/{wallet_address}
Returns the native ETH balance for the specified wallet address. Lightweight endpoint for quick balance checks.
Getting Started
Clone and install:
git clone https://github.com/tunmi-stom/token-nft_portfolio_api.git
cd token-nft_portfolio_api
python -m venv venv
source venv/bin/activate # Linux/macOS
# venv\Scripts\activate # Windows
pip install -r requirements.txt
Configure your environment:
# .env
MORALIS_API_KEY=your_api_key_here
Start the server:
uvicorn app.main:app --reload
The API will be live at http://127.0.0.1:8000. Hit /docs for the interactive Swagger UI, or /redoc for the ReDoc interface.
Design Decisions Worth Talking About
Why async?
Blockchain data fetching is I/O-bound. When a single portfolio request might fan out into three separate API calls (native balance, ERC-20s, NFTs), running them sequentially is wasteful. FastAPI's async support with httpx lets those calls happen concurrently, cutting response times significantly.
Use Cases
This API is intentionally generic at its core, but the endpoints map directly to real product surfaces:
- NFT portfolio dashboards — display a collector's holdings with live metadata
- Wallet explorers — let users paste an address and see everything it holds
- Blockchain analytics platforms — feed aggregated token data into charts and reports
- Crypto accounting tools — pull balances for tax lot tracking or portfolio valuation
- Web3 portfolio managers — show users their Ethereum portfolio value in one view
What's Coming Next
The current version is a solid read-only data layer. Here's where it goes from here:
- Transaction history — full inbound/outbound history per wallet
- Multi-wallet support — aggregate across multiple addresses in a single request
- USD portfolio valuation — attach live price feeds to compute total value
- Caching layer — Redis-backed TTL caching to reduce Moralis API calls under load
- Authentication & rate limiting — per-API-key auth and usage throttling
- Solana support — extend the service layer to SPL tokens and Metaplex NFTs
- WebSocket live updates — push balance changes to connected clients in real time
- Docker deployment — containerized setup for consistent prod/dev environments
Wrapping Up
This project started as a personal tool and grew into something I wanted other developers to be able to use. Querying Ethereum data cleanly — across ETH balances, ERC-20 tokens, and NFTs — is more work than it looks. FastAPI makes it manageable, and Pydantic keeps the response shapes honest.
The full source is on GitHub: github.com/tunmi-stom/token-nft_portfolio_api
Contributions are welcome. Fork it, open an issue, or build something with it.
Built by Tunmise Ola.
Top comments (0)