ethcontract_common/
contract.rs1use crate::abiext::FunctionExt;
4use crate::hash::H32;
5use crate::Abi;
6use crate::{bytecode::Bytecode, DeploymentInformation};
7use ethabi::ethereum_types::H256;
8use serde::Deserializer;
9use serde::Serializer;
10use serde::{Deserialize, Serialize};
11use std::collections::{BTreeMap, HashMap};
12use std::hash::Hash;
13use std::sync::Arc;
14use web3::types::Address;
15
16#[derive(Clone, Debug, Serialize, Deserialize)]
18#[serde(default = "Contract::empty")]
19pub struct Contract {
20 #[serde(rename = "contractName")]
22 pub name: String,
23 #[serde(rename = "abi")]
25 pub interface: Arc<Interface>,
26 pub bytecode: Bytecode,
28 #[serde(rename = "deployedBytecode")]
30 pub deployed_bytecode: Bytecode,
31 pub networks: HashMap<String, Network>,
33 pub devdoc: Documentation,
35 pub userdoc: Documentation,
37}
38
39#[derive(Clone, Debug, Default, PartialEq)]
41pub struct Interface {
42 pub abi: Abi,
44 pub methods: HashMap<H32, (String, usize)>,
48 pub events: HashMap<H256, (String, usize)>,
51}
52
53impl<'de> Deserialize<'de> for Interface {
54 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
55 where
56 D: Deserializer<'de>,
57 {
58 let abi = Abi::deserialize(deserializer)?;
59 Ok(abi.into())
60 }
61}
62
63impl Serialize for Interface {
64 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
65 where
66 S: Serializer,
67 {
68 self.abi.serialize(serializer)
69 }
70}
71
72impl From<Abi> for Interface {
73 fn from(abi: Abi) -> Self {
74 Self {
75 methods: create_mapping(&abi.functions, |function| function.selector()),
76 events: create_mapping(&abi.events, |event| event.signature()),
77 abi,
78 }
79 }
80}
81
82fn create_mapping<T, S, F>(
85 elements: &BTreeMap<String, Vec<T>>,
86 signature: F,
87) -> HashMap<S, (String, usize)>
88where
89 S: Hash + Eq + Ord,
90 F: Fn(&T) -> S,
91{
92 let signature = &signature;
93 elements
94 .iter()
95 .flat_map(|(name, sub_elements)| {
96 sub_elements
97 .iter()
98 .enumerate()
99 .map(move |(index, element)| (signature(element), (name.to_owned(), index)))
100 })
101 .collect()
102}
103
104impl Contract {
105 pub fn empty() -> Self {
107 Contract::with_name(String::default())
108 }
109
110 pub fn with_name(name: impl Into<String>) -> Self {
112 Contract {
113 name: name.into(),
114 interface: Default::default(),
115 bytecode: Default::default(),
116 deployed_bytecode: Default::default(),
117 networks: HashMap::new(),
118 devdoc: Default::default(),
119 userdoc: Default::default(),
120 }
121 }
122}
123
124#[derive(Clone, Debug, Serialize, Deserialize)]
126pub struct Network {
127 pub address: Address,
129 #[serde(rename = "transactionHash")]
131 pub deployment_information: Option<DeploymentInformation>,
132}
133
134#[derive(Clone, Debug, Default, Serialize, Deserialize)]
136pub struct Documentation {
137 pub details: Option<String>,
139 pub methods: HashMap<String, DocEntry>,
141}
142
143#[derive(Clone, Debug, Default, Serialize, Deserialize)]
144pub struct DocEntry {
146 pub details: Option<String>,
148}