diff --git a/packages/komodo_cex_market_data/lib/src/coingecko/data/coingecko_cex_provider.dart b/packages/komodo_cex_market_data/lib/src/coingecko/data/coingecko_cex_provider.dart index af8403c8e..f2f5a5408 100644 --- a/packages/komodo_cex_market_data/lib/src/coingecko/data/coingecko_cex_provider.dart +++ b/packages/komodo_cex_market_data/lib/src/coingecko/data/coingecko_cex_provider.dart @@ -565,10 +565,17 @@ class CoinGeckoCexProvider implements ICoinGeckoProvider { 'Requested: $days days. Maximum allowed: 365 days.', ); } + // Snap to CoinGecko OHLC-supported day buckets + final int snappedDays = _normalizeOhlcDaysParam(days); + if (snappedDays != days) { + _logger.fine( + 'Snapped OHLC days from $days to $snappedDays to satisfy CoinGecko constraints', + ); + } final queryParameters = { 'id': id, 'vs_currency': vsCurrency, - 'days': days.toString(), + 'days': snappedDays.toString(), if (precision != null) 'precision': precision.toString(), }; @@ -588,6 +595,21 @@ class CoinGeckoCexProvider implements ICoinGeckoProvider { }); } + /// Normalizes the OHLC `days` parameter to the nearest allowed bucket for CoinGecko: + /// 1, 7, 14, 30, 90, 180, 365. + /// Strategy: round up to the next allowed bucket to avoid under-fetching. + int _normalizeOhlcDaysParam(int requestedDays) { + if (requestedDays <= 1) return 1; + const List allowed = [1, 7, 14, 30, 90, 180, 365]; + for (final int value in allowed) { + if (requestedDays <= value) { + return value; + } + } + // Fallback safeguard (should be capped earlier) + return 365; + } + /// Throws an [Exception] with a properly formatted error message. /// /// This method consolidates the error handling logic that was repeated