Skip to content

Commit

Permalink
chore: include value in serde error (#29)
Browse files Browse the repository at this point in the history
a few etherscan APIs are truly bad.
A lot of them randomly send HTML content instead of proper json errors,
resulting in unhelpful error messages:

> expected value at line 1 column 1


we already have a few checks for HTML content but because we don't
capture the content we cant easily add more.

this includes the content in the error message, so even if this could
make the error message very verbose, this is still more helpful because
now we easily get reference data.
  • Loading branch information
mattsse authored Jan 26, 2024
1 parent d6c266a commit 8da1e32
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 8 deletions.
12 changes: 9 additions & 3 deletions src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,11 @@ impl SourceCodeMetadata {
if value.is_null() {
Ok(None)
} else {
Ok(Some(serde_json::from_value(value.to_owned())?))
let settings =
serde_json::from_value(value.to_owned()).map_err(|error| {
EtherscanError::Serde { error, content: value.to_string() }
})?;
Ok(Some(settings))
}
}
None => Ok(None),
Expand Down Expand Up @@ -193,7 +197,8 @@ impl Metadata {

/// Parses the ABI string into a [`JsonAbi`] struct.
pub fn abi(&self) -> Result<JsonAbi> {
serde_json::from_str(&self.abi).map_err(Into::into)
serde_json::from_str(&self.abi)
.map_err(|error| EtherscanError::Serde { error, content: self.abi.clone() })
}

/// Parses the compiler version.
Expand Down Expand Up @@ -380,7 +385,8 @@ impl Client {
}
return Err(EtherscanError::ContractCodeNotVerified(address));
}
let abi = serde_json::from_str(&result)?;
let abi = serde_json::from_str(&result)
.map_err(|error| EtherscanError::Serde { error, content: result })?;

if let Some(ref cache) = self.cache {
cache.set_abi(address, Some(&abi));
Expand Down
4 changes: 2 additions & 2 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ pub enum EtherscanError {
EnvVarNotFound(#[from] VarError),
#[error(transparent)]
Reqwest(#[from] reqwest::Error),
#[error(transparent)]
Serde(#[from] serde_json::Error),
#[error("Failed to deserialize content: {error}\n{content}")]
Serde { error: serde_json::Error, content: String },
#[error("Contract source code not verified: {0}")]
ContractCodeNotVerified(Address),
#[error("Response result is unexpectedly empty: status={status}, message={message}")]
Expand Down
6 changes: 3 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -225,16 +225,16 @@ impl Client {
/// Perform sanity checks on a response and deserialize it into a [Response].
fn sanitize_response<T: DeserializeOwned>(&self, res: impl AsRef<str>) -> Result<Response<T>> {
let res = res.as_ref();
let res: ResponseData<T> = serde_json::from_str(res).map_err(|err| {
error!(target: "etherscan", ?res, "Failed to deserialize response: {}", err);
let res: ResponseData<T> = serde_json::from_str(res).map_err(|error| {
error!(target: "etherscan", ?res, "Failed to deserialize response: {}", error);
if res == "Page not found" {
EtherscanError::PageNotFound
} else if is_blocked_by_cloudflare_response(res) {
EtherscanError::BlockedByCloudflare
} else if is_cloudflare_security_challenge(res) {
EtherscanError::CloudFlareSecurityChallenge
} else {
EtherscanError::Serde(err)
EtherscanError::Serde { error, content: res.to_string() }
}
})?;

Expand Down

0 comments on commit 8da1e32

Please sign in to comment.