fetchEtherscanWithRatelimitRetries<T> method

Future<T> fetchEtherscanWithRatelimitRetries<T>(
  1. String rawEndpoint, {
  2. int maxRetries = 10,
})
inherited

Implementation

Future<T> fetchEtherscanWithRatelimitRetries<T>(
  String rawEndpoint, {
  int maxRetries = 10,
}) async {
  final baseEndpoint = getBaseEtherscanEndpoint(rawEndpoint);

  bool maybeUseApiKey = false;

  for (var i = 0; i < maxRetries; i++) {
    String endpoint = rawEndpoint;
    String? currentApiKey;

    if (_needsApiKey(baseEndpoint)) {
      maybeUseApiKey = false;
      currentApiKey = _getRandomApiKey();
      if (currentApiKey == null) {
        Logger.logError("No available API keys");
        throw Exception("No available API keys");
      }
      endpoint = "$rawEndpoint&apikey=$currentApiKey";
    } else if (maybeUseApiKey) {
      maybeUseApiKey = false;
      currentApiKey = _getRandomApiKey();
      if (currentApiKey != null) {
        endpoint = "$rawEndpoint&apikey=$currentApiKey";
      }
    }

    final response = await HTTPService.client.get(
      Uri.parse(endpoint),
      headers: _buildRequestHeaders(),
    );

    if (response.statusCode == 200) {
      final body = jsonDecode(response.body);
      int status = int.tryParse(body['status'] ?? '') ?? -1;
      final result = body['result'];

      if (status == 1) return result;

      if (status == 0) {
        final result_s = result is String ? result : 'empty';
        if (result == null) {
          continue;
        }

        if (result == "Missing/Invalid API Key") {
          _setNeedsApiKey(baseEndpoint, true);
        } else if (result_s.contains('Invalid API Key')) {
          invalidApiKeys.add(currentApiKey!);
          if (_getRandomApiKey() == null) {
            await Future.delayed(noApiKeyRetryIntervall);
          } else {
            maybeUseApiKey = true; // Try again with an API key
          }
        } else if (result_s.contains("Max daily rate limit")) {
          if (currentApiKey != null) {
            _excludeApiKey(currentApiKey);
          }
          if (_getRandomApiKey() == null) {
            await Future.delayed(noApiKeyRetryIntervall);
          } else {
            maybeUseApiKey = true; // Try again with an API key
          }
        } else if (result_s.contains('for higher rate limit')) {
          if (_getRandomApiKey() == null) {
            await Future.delayed(noApiKeyRetryIntervall);
          } else {
            maybeUseApiKey = true; // Try again with an API key
          }
        } else if (result_s.contains("Max calls per sec")) {
          await Future.delayed(apiKeyRetryIntervall);
        } else {
          String message = body['message'];
          if (message != "NOTOK") return result;
        }
      }
    }
  }

  throw Exception("Failed to fetch $rawEndpoint after $maxRetries retries");
}