Implementing NFT Collection Display in Mobile Wallet
User connects wallet—and expects to see their NFTs with preview, name, and collection. In reality: some metadata sits on IPFS with inaccessible gateways, some tokens exist in multiple networks simultaneously, images range from 10 KB to 50 MB. All must display quickly without crashes.
Data Sources for NFT Display
Direct RPC calls to ERC-721 (tokenURI, ownerOf) for each token mean dozens of parallel requests. For a wallet with 50+ NFTs, this approach is impractical. Use aggregating APIs:
-
Alchemy NFT API (
getNFTsForOwner)—returns all NFTs by address with metadata and media URL, supports Ethereum, Polygon, Base, Arbitrum - Moralis Web3 API—similar, plus Solana and BNB Chain support
- OpenSea API v2—relevant if the app includes trading, provides prices and floor price
- QuickNode NFT API—suitable for multi-chain wallets with custom RPC
For Solana: getTokenAccountsByOwner via JSON-RPC + Metaplex getAssetsByOwner (DAS API) for metadata.
The aggregator response already contains media[0].gateway—a normalized image URL, not raw IPFS hash. This matters: ipfs://Qm... can't load directly in AsyncImage or Glide—needs a public gateway.
IPFS and Unreliable Media URLs
Some NFTs store metadata and images on IPFS via ipfs:// scheme. Public gateways (ipfs.io, cloudflare-ipfs.com, gateway.pinata.cloud) often lag or are unavailable. Solution: try multiple gateways sequentially with 3-second timeout, show placeholder, load in background.
For SVG, animated GIF, 3D GLB media—separate handling needed. SVG on iOS renders via SVGKit or WebView. GLB—via SceneKit/RealityKit or model-viewer in WebView. GIF—FLAnimatedImage (iOS) or Coil with GIF decoder (Android).
Gallery Structure and Filtering
Group tokens by collection (contractAddress + name). Display in sections: collection name, token count, floor price (if available). Within section—2–3 column grid.
iOS: UICollectionViewCompositionalLayout with NSCollectionLayoutSection for sections + UICollectionViewDiffableDataSource for smooth updates. On first load, show skeleton cells via UIView.animate.
Android: LazyVerticalGrid in Compose or RecyclerView with GridLayoutManager + ConcatAdapter for sections. Image loading—Coil with disk caching (DiskCachePolicy.ENABLED).
Flutter: SliverGrid within CustomScrollView, images via cached_network_image with cacheManager.
Multi-Chain Filtering
In a wallet supporting Ethereum + Polygon + Base, users need to switch networks quickly. Store NFTs locally in Room/CoreData/Hive with chainId field. Filter changes the database query—no repeat network requests.
Detailed Token Screen
Display: image/video/3D, name, collection, description, attributes (traits) as tags with rarity percentages if API provides them. Links to OpenSea/Blur/Magic Eden. Transaction history via getTransfersForToken API.
Timeline: implementing NFT gallery with 2–3 network support, metadata, and token details—3–5 working days. Multi-chain with trading functions—1–2 weeks.







