feat(contract, abigen): support artifact format in proc macro (#480)

* feat(contract, abigen): support artifact format in proc macro

* don't change source abi_str
This commit is contained in:
Alexey Shekhirin 2021-10-02 20:16:55 +03:00 committed by GitHub
parent 42bf98330b
commit 1f17788133
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 20 additions and 8 deletions

View File

@ -10,14 +10,14 @@ use super::Abigen;
use crate::contract::structs::InternalStructs; use crate::contract::structs::InternalStructs;
use crate::rawabi::RawAbi; use crate::rawabi::RawAbi;
use anyhow::{anyhow, Context as _, Result}; use anyhow::{anyhow, Context as _, Result};
use ethers_core::abi::AbiParser;
use ethers_core::{ use ethers_core::{
abi::{parse_abi, Abi}, abi::{parse_abi, Abi, AbiParser},
types::Address, types::Address,
}; };
use inflector::Inflector; use inflector::Inflector;
use proc_macro2::{Ident, Literal, TokenStream}; use proc_macro2::{Ident, Literal, TokenStream};
use quote::quote; use quote::quote;
use serde::Deserialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use syn::{Path, Visibility}; use syn::{Path, Visibility};
@ -121,13 +121,25 @@ impl Context {
// get the actual ABI string // get the actual ABI string
let abi_str = args.abi_source.get().context("failed to get ABI JSON")?; let abi_str = args.abi_source.get().context("failed to get ABI JSON")?;
let mut abi_parser = AbiParser::default(); let mut abi_parser = AbiParser::default();
// parse it
let (abi, human_readable): (Abi, _) = if let Ok(abi) = serde_json::from_str(&abi_str) { let (abi, human_readable): (Abi, _) = if let Ok(abi) = abi_parser.parse_str(&abi_str) {
// normal abi format (abi, true)
(abi, false)
} else { } else {
// heuristic for parsing the human readable format // a best-effort coercion of an ABI or an artifact JSON into an artifact JSON.
(abi_parser.parse_str(&abi_str)?, true) let json_abi_str = if abi_str.trim().starts_with('[') {
format!(r#"{{"abi":{}}}"#, abi_str.trim())
} else {
abi_str.clone()
};
#[derive(Deserialize)]
struct Contract {
abi: Abi,
}
let contract = serde_json::from_str::<Contract>(&json_abi_str)?;
(contract.abi, false)
}; };
// try to extract all the solidity structs from the normal JSON ABI // try to extract all the solidity structs from the normal JSON ABI