fix(etherscan): source code serde (#1962)
This commit is contained in:
parent
5008006767
commit
1baf88138f
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
source_tree::{SourceTree, SourceTreeEntry},
|
||||
utils::{deserialize_address_opt, deserialize_stringified_source_code},
|
||||
utils::{deserialize_address_opt, deserialize_source_code},
|
||||
Client, EtherscanError, Response, Result,
|
||||
};
|
||||
use ethers_core::{
|
||||
|
@ -107,7 +107,7 @@ impl SourceCodeMetadata {
|
|||
#[serde(rename_all = "PascalCase")]
|
||||
pub struct Metadata {
|
||||
/// Includes metadata for compiler settings and language.
|
||||
#[serde(deserialize_with = "deserialize_stringified_source_code")]
|
||||
#[serde(deserialize_with = "deserialize_source_code")]
|
||||
pub source_code: SourceCodeMetadata,
|
||||
|
||||
/// The ABI of the contract.
|
||||
|
@ -148,7 +148,11 @@ pub struct Metadata {
|
|||
pub proxy: u64,
|
||||
|
||||
/// If this contract is a proxy, the address of its implementation.
|
||||
#[serde(deserialize_with = "deserialize_address_opt")]
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "deserialize_address_opt"
|
||||
)]
|
||||
pub implementation: Option<Address>,
|
||||
|
||||
/// The swarm source of the contract.
|
||||
|
|
|
@ -36,21 +36,36 @@ pub fn deserialize_address_opt<'de, D: Deserializer<'de>>(
|
|||
|
||||
/// Deserializes as JSON:
|
||||
///
|
||||
/// `{ "SourceCode": "{{ .. }}", ..}`
|
||||
/// Object: `{ "SourceCode": { language: "Solidity", .. }, ..}`
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// `{ "SourceCode": "..", .. }`
|
||||
pub fn deserialize_stringified_source_code<'de, D: Deserializer<'de>>(
|
||||
/// Stringified JSON: `{ "SourceCode": "{{\r\n \"language\": \"Solidity\", ..}}", ..}`
|
||||
///
|
||||
/// or
|
||||
///
|
||||
/// Normal source code: `{ "SourceCode": "// SPDX-License-Identifier: ...", .. }`
|
||||
pub fn deserialize_source_code<'de, D: Deserializer<'de>>(
|
||||
deserializer: D,
|
||||
) -> std::result::Result<SourceCodeMetadata, D::Error> {
|
||||
let s = String::deserialize(deserializer)?;
|
||||
#[derive(Deserialize)]
|
||||
#[serde(untagged)]
|
||||
enum SourceCode {
|
||||
String(String), // this must come first
|
||||
Obj(SourceCodeMetadata),
|
||||
}
|
||||
let s = SourceCode::deserialize(deserializer)?;
|
||||
match s {
|
||||
SourceCode::String(s) => {
|
||||
if s.starts_with("{{") && s.ends_with("}}") {
|
||||
let s = &s[1..s.len() - 1];
|
||||
serde_json::from_str(s).map_err(serde::de::Error::custom)
|
||||
} else {
|
||||
Ok(SourceCodeMetadata::SourceCode(s))
|
||||
}
|
||||
}
|
||||
SourceCode::Obj(obj) => Ok(obj),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -108,17 +123,29 @@ mod tests {
|
|||
}
|
||||
|
||||
#[test]
|
||||
fn can_deserialize_stringified_source_code() {
|
||||
fn can_deserialize_source_code() {
|
||||
#[derive(Deserialize)]
|
||||
struct Test {
|
||||
#[serde(deserialize_with = "deserialize_stringified_source_code")]
|
||||
#[serde(deserialize_with = "deserialize_source_code")]
|
||||
source_code: SourceCodeMetadata,
|
||||
}
|
||||
|
||||
let src = "source code text";
|
||||
|
||||
// Normal JSON
|
||||
let json = r#"{
|
||||
"source_code": "{{ \"language\": \"Solidity\", \"sources\": {\"Contract\": { \"content\": \"source code text\" } } }}"
|
||||
"source_code": { "language": "Solidity", "sources": { "Contract": { "content": "source code text" } } }
|
||||
}"#;
|
||||
let de: Test = serde_json::from_str(json).unwrap();
|
||||
assert!(matches!(de.source_code.language().unwrap(), SourceCodeLanguage::Solidity));
|
||||
assert_eq!(de.source_code.sources().len(), 1);
|
||||
assert_eq!(de.source_code.sources().get("Contract").unwrap().content, src);
|
||||
#[cfg(feature = "ethers-solc")]
|
||||
assert!(matches!(de.source_code.settings().unwrap(), None));
|
||||
|
||||
// Stringified JSON
|
||||
let json = r#"{
|
||||
"source_code": "{{ \"language\": \"Solidity\", \"sources\": { \"Contract\": { \"content\": \"source code text\" } } }}"
|
||||
}"#;
|
||||
let de: Test = serde_json::from_str(json).unwrap();
|
||||
assert!(matches!(de.source_code.language().unwrap(), SourceCodeLanguage::Solidity));
|
||||
|
|
Loading…
Reference in New Issue