use crate::abiext::FunctionExt;
use crate::hash::H32;
use crate::Abi;
use crate::{bytecode::Bytecode, DeploymentInformation};
use ethabi::ethereum_types::H256;
use serde::Deserializer;
use serde::Serializer;
use serde::{Deserialize, Serialize};
use std::collections::{BTreeMap, HashMap};
use std::hash::Hash;
use std::sync::Arc;
use web3::types::Address;
#[derive(Clone, Debug, Serialize, Deserialize)]
#[serde(default = "Contract::empty")]
pub struct Contract {
#[serde(rename = "contractName")]
pub name: String,
#[serde(rename = "abi")]
pub interface: Arc<Interface>,
pub bytecode: Bytecode,
#[serde(rename = "deployedBytecode")]
pub deployed_bytecode: Bytecode,
pub networks: HashMap<String, Network>,
pub devdoc: Documentation,
pub userdoc: Documentation,
}
#[derive(Clone, Debug, Default, PartialEq)]
pub struct Interface {
pub abi: Abi,
pub methods: HashMap<H32, (String, usize)>,
pub events: HashMap<H256, (String, usize)>,
}
impl<'de> Deserialize<'de> for Interface {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let abi = Abi::deserialize(deserializer)?;
Ok(abi.into())
}
}
impl Serialize for Interface {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
self.abi.serialize(serializer)
}
}
impl From<Abi> for Interface {
fn from(abi: Abi) -> Self {
Self {
methods: create_mapping(&abi.functions, |function| function.selector()),
events: create_mapping(&abi.events, |event| event.signature()),
abi,
}
}
}
fn create_mapping<T, S, F>(
elements: &BTreeMap<String, Vec<T>>,
signature: F,
) -> HashMap<S, (String, usize)>
where
S: Hash + Eq + Ord,
F: Fn(&T) -> S,
{
let signature = &signature;
elements
.iter()
.flat_map(|(name, sub_elements)| {
sub_elements
.iter()
.enumerate()
.map(move |(index, element)| (signature(element), (name.to_owned(), index)))
})
.collect()
}
impl Contract {
pub fn empty() -> Self {
Contract::with_name(String::default())
}
pub fn with_name(name: impl Into<String>) -> Self {
Contract {
name: name.into(),
interface: Default::default(),
bytecode: Default::default(),
deployed_bytecode: Default::default(),
networks: HashMap::new(),
devdoc: Default::default(),
userdoc: Default::default(),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct Network {
pub address: Address,
#[serde(rename = "transactionHash")]
pub deployment_information: Option<DeploymentInformation>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct Documentation {
pub details: Option<String>,
pub methods: HashMap<String, DocEntry>,
}
#[derive(Clone, Debug, Default, Serialize, Deserialize)]
pub struct DocEntry {
pub details: Option<String>,
}