From 862d923f2a789162ba62d048fe7a572c86274f4a Mon Sep 17 00:00:00 2001 From: Matthias Seitz Date: Mon, 13 Mar 2023 20:43:17 +0100 Subject: [PATCH] fix(etherscan): support null result (#2249) --- ethers-etherscan/src/errors.rs | 2 ++ ethers-etherscan/src/lib.rs | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/ethers-etherscan/src/errors.rs b/ethers-etherscan/src/errors.rs index f6cc587dd..5f71f52d9 100644 --- a/ethers-etherscan/src/errors.rs +++ b/ethers-etherscan/src/errors.rs @@ -29,6 +29,8 @@ pub enum EtherscanError { IO(#[from] std::io::Error), #[error("Local networks (e.g. anvil, ganache, geth --dev) cannot be indexed by etherscan")] LocalNetworksNotSupported, + #[error("Received error response: status={status},message={message}, result={result:?}")] + ErrorResponse { status: String, message: String, result: Option }, #[error("Unknown error: {0}")] Unknown(String), #[error("Missing field: {0}")] diff --git a/ethers-etherscan/src/lib.rs b/ethers-etherscan/src/lib.rs index 99b3397b8..453eaefb0 100644 --- a/ethers-etherscan/src/lib.rs +++ b/ethers-etherscan/src/lib.rs @@ -214,14 +214,15 @@ impl Client { })?; match res { - ResponseData::Error { result, .. } => { - if result.starts_with("Max rate limit reached") { - Err(EtherscanError::RateLimitExceeded) - } else if result.to_lowercase() == "invalid api key" { - Err(EtherscanError::InvalidApiKey) - } else { - Err(EtherscanError::Unknown(result)) + ResponseData::Error { result, message, status } => { + if let Some(ref result) = result { + if result.starts_with("Max rate limit reached") { + return Err(EtherscanError::RateLimitExceeded) + } else if result.to_lowercase() == "invalid api key" { + return Err(EtherscanError::InvalidApiKey) + } } + Err(EtherscanError::ErrorResponse { status, message, result }) } ResponseData::Success(res) => Ok(res), } @@ -426,7 +427,7 @@ pub struct Response { #[serde(untagged)] pub enum ResponseData { Success(Response), - Error { status: String, message: String, result: String }, + Error { status: String, message: String, result: Option }, } /// The type that gets serialized as query @@ -461,9 +462,17 @@ fn into_url(url: impl IntoUrl) -> std::result::Result { #[cfg(test)] mod tests { - use crate::{Client, EtherscanError}; + use crate::{Client, EtherscanError, ResponseData}; use ethers_core::types::{Address, Chain, H256}; + // + #[test] + fn can_parse_block_scout_err() { + let err = "{\"message\":\"Something went wrong.\",\"result\":null,\"status\":\"0\"}"; + let resp: ResponseData
= serde_json::from_str(err).unwrap(); + assert!(matches!(resp, ResponseData::Error { .. })); + } + #[test] fn test_api_paths() { let client = Client::new(Chain::Goerli, "").unwrap();