NFT Price History in Mobile App
An NFT collection looks like a set of JPEGs until you see its floor price grow from 0.05 to 12 ETH in three weeks. It's price history that turns an NFT tracker from a static catalog into an analytical tool.
Price History Source
Blockchain itself doesn't store "price history" as an entity. An NFT sale is a Transfer event in an ERC-721 smart contract plus ETH movement between addresses in the same transaction. To build price history, you need to aggregate on-chain events. Self-parsing Ethereum is expensive. So use specialized APIs:
OpenSea API v2 (/api/v2/events/collection/{slug}) returns sale type events with price in wei and timestamp. Limitation—4 requests per second on free key. For history deeper than 30 days, need paid plan.
Reservoir API (/sales/v6)—more generous with history depth and rate limits. Supports multiple marketplaces simultaneously (OpenSea, Blur, X2Y2). Pagination via continuation token.
Alchemy NFT API (/getNFTSales)—convenient if already using Alchemy for other on-chain requests.
On Flutter typical repository looks like:
class NftSalesRepository {
final Dio _dio;
final String _reservoirKey;
Future<List<NftSale>> getSalesHistory({
required String contractAddress,
required String tokenId,
DateTime? from,
}) async {
final params = {
'tokens': '$contractAddress:$tokenId',
'startTimestamp': from?.millisecondsSinceEpoch ~/ 1000,
'limit': 100,
};
final resp = await _dio.get(
'https://api.reservoir.tools/sales/v6',
queryParameters: params,
options: Options(headers: {'x-api-key': _reservoirKey}),
);
return (resp.data['sales'] as List)
.map((e) => NftSale.fromJson(e))
.toList();
}
}
Price comes in ETH (or other network native currency), but users expect to see USD. ETH/USD rate must be pulled separately—via CoinGecko API or Alchemy Price API, cached with TTL 60 seconds and applied to historical points post-factum.
Visualization
For chart rendering on Flutter, fl_chart works well. Sales data needs normalization before render: remove obvious wash-trade outliers (sale between related wallets at off-market price), aggregate by days or weeks depending on history depth.
On React Native—Victory Native XL (works on Reanimated 3, no bridge redraws) or react-native-gifted-charts.
LineChart(
LineChartData(
lineBarsData: [
LineChartBarData(
spots: sales.map((s) => FlSpot(
s.timestamp.toDouble(),
s.priceUsd,
)).toList(),
isCurved: true,
gradient: LinearGradient(colors: [Colors.purple, Colors.blue]),
belowBarData: BarAreaData(show: true, color: Colors.purple.withOpacity(0.1)),
),
],
titlesData: FlTitlesData(
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) => _formatDate(value),
),
),
),
),
)
What's Included
- Reservoir API or OpenSea API integration with pagination
- Data models:
NftSale,PricePointwith wei → ETH → USD conversion - SQLite caching (drift/floor) with TTL
- Chart with time range selection (7d / 30d / All)
- Empty history and network error handling
Timeline
2–4 business days depending on platform and chart design complexity. Cost is calculated individually after requirements analysis.







