Skip to content

Commit

Permalink
Deserialize ResponseData using status for error and success
Browse files Browse the repository at this point in the history
  • Loading branch information
JonoPrest committed Jul 23, 2024
1 parent 272e60d commit 3208751
Showing 1 changed file with 23 additions and 7 deletions.
30 changes: 23 additions & 7 deletions crates/block-explorers/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ impl Client {
})?;

match res {
ResponseData::Error { result, message, status } => {
ResponseData::Error { message, result } => {
if let Some(ref result) = result {
if result.starts_with("Max rate limit reached") {
return Err(EtherscanError::RateLimitExceeded);
Expand All @@ -250,9 +250,11 @@ impl Client {
return Err(EtherscanError::InvalidApiKey);
}
}
Err(EtherscanError::ErrorResponse { status, message, result })
Err(EtherscanError::ErrorResponse { status: "0".to_string(), message, result })
}
ResponseData::Success { message, result } => {
Ok(Response { status: "1".to_string(), message, result })
}
ResponseData::Success(res) => Ok(res),
}
}

Expand Down Expand Up @@ -496,11 +498,13 @@ pub struct Response<T> {
pub result: T,
}

#[derive(Deserialize, Debug, Clone)]
#[serde(untagged)]
#[derive(Debug, Clone, Deserialize)]
#[serde(tag = "status")]
pub enum ResponseData<T> {
Success(Response<T>),
Error { status: String, message: String, result: Option<String> },
#[serde(rename = "1")]
Success { message: String, result: T },
#[serde(rename = "0")]
Error { message: String, result: Option<String> },
}

/// The type that gets serialized as query
Expand Down Expand Up @@ -528,6 +532,7 @@ mod tests {
use crate::{Client, EtherscanError, ResponseData};
use alloy_chains::Chain;
use alloy_primitives::{Address, B256};
use serde_json::json;

// <https://github.com/foundry-rs/foundry/issues/4406>
#[test]
Expand All @@ -537,6 +542,17 @@ mod tests {
assert!(matches!(resp, ResponseData::Error { .. }));
}

#[test]
fn can_parse_etherscan_mainnet_invalid_api_key() {
let err = json!({
"status":"0",
"message":"NOTOK",
"result":"Missing/Invalid API Key"
});
let resp: ResponseData<Address> = serde_json::from_value(err).unwrap();
assert!(matches!(resp, ResponseData::Error { .. }));
}

#[test]
fn test_api_paths() {
let client = Client::new(Chain::goerli(), "").unwrap();
Expand Down

0 comments on commit 3208751

Please sign in to comment.