use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
use crate::ast::{self, FunctionType};
#[derive(Default, Serialize, Deserialize, Debug, PartialEq, Eq, Clone)]
pub struct Abi {
pub constructor: Option<Constructor>,
pub functions: BTreeMap<String, Function>,
pub events: BTreeMap<String, Event>,
pub receive: bool,
pub fallback: bool,
}
impl Abi {
pub fn new() -> Self {
Self::default()
}
}
impl From<ast::Contract> for Abi {
fn from(contract: ast::Contract) -> Self {
let constructors: Vec<ast::Function> = contract
.functions
.iter()
.filter(|function: &&ast::Function| function.name == "CONSTRUCTOR")
.cloned()
.collect();
let constructor: ast::Function = constructors.get(0).unwrap().clone();
let mut functions = BTreeMap::new();
let mut events = BTreeMap::new();
contract
.functions
.iter()
.filter(|function: &&ast::Function| function.name != "CONSTRUCTOR")
.map(|function| {
(
function.name.to_string(),
Function {
name: function.name.to_string(),
inputs: function
.inputs
.iter()
.map(|argument| FunctionParam {
name: argument.name.clone().unwrap_or_default(),
kind: argument.arg_type.clone().unwrap_or_default().into(),
internal_type: None,
})
.collect(),
outputs: function
.outputs
.iter()
.map(|argument| FunctionParam {
name: argument.name.clone().unwrap_or_default(),
kind: argument.arg_type.clone().unwrap_or_default().into(),
internal_type: None,
})
.collect(),
constant: false,
state_mutability: function.fn_type.clone(),
},
)
})
.for_each(|val| {
let _ = functions.insert(val.0, val.1);
});
contract
.events
.iter()
.map(|event| {
(
event.name.to_string(),
Event {
name: event.name.to_string(),
inputs: event
.parameters
.iter()
.map(|argument| EventParam {
name: argument.name.clone().unwrap_or_default(),
kind: argument.arg_type.clone().unwrap_or_default().into(),
indexed: false, })
.collect(),
anonymous: false,
},
)
})
.for_each(|val| {
let _ = events.insert(val.0, val.1);
});
Self {
constructor: Some(Constructor {
inputs: constructor
.inputs
.iter()
.map(|argument| FunctionParam {
name: argument.name.clone().unwrap_or_default(),
kind: argument.arg_type.clone().unwrap_or_default().into(),
internal_type: None,
})
.collect(),
}),
functions,
events,
receive: false,
fallback: false,
}
}
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Function {
pub name: String,
pub inputs: Vec<FunctionParam>,
pub outputs: Vec<FunctionParam>,
pub constant: bool,
pub state_mutability: FunctionType,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Event {
pub name: String,
pub inputs: Vec<EventParam>,
pub anonymous: bool,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct EventParam {
pub name: String,
pub kind: FunctionParamType,
pub indexed: bool,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct Constructor {
pub inputs: Vec<FunctionParam>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub struct FunctionParam {
pub name: String,
pub kind: FunctionParamType,
pub internal_type: Option<String>,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq, PartialOrd, Ord, Clone)]
pub enum FunctionParamType {
Address,
Bytes,
Int(usize),
Uint(usize),
Bool,
String,
Array(Box<FunctionParamType>),
FixedBytes(usize),
FixedArray(Box<FunctionParamType>, usize),
Tuple(Vec<FunctionParamType>),
}
impl From<&str> for FunctionParamType {
fn from(string: &str) -> Self {
match string {
"Address" | "address" => Self::Address,
"Bytes" | "bytes" => Self::Bytes,
"Int" | "int" | "integer" | "Integer" => Self::Int(0),
"Uint" | "uint" | "unsignedinteger" | "unsigned integer" => Self::Uint(0),
"Bool" | "bool" => Self::Bool,
"String" | "string" | "str" | "Str" => Self::String,
"Array" | "array" => Self::Array(Box::new(FunctionParamType::Bool)),
"FixedBytes" | "bytes32" => Self::Array(Box::new(FunctionParamType::Bool)),
_ => {
tracing::error!(
"{}",
format!("Failed to create FunctionParamType from string: {}", string)
);
panic!("{}", format!("Failed to create FunctionParamType from string: {}", string))
}
}
}
}
impl From<String> for FunctionParamType {
fn from(string: String) -> Self {
match string.as_ref() {
"Address" | "address" => Self::Address,
"Bytes" | "bytes" => Self::Bytes,
"Int" | "int" | "integer" | "Integer" => Self::Int(0),
"Uint" | "uint" | "unsignedinteger" | "unsigned integer" => Self::Uint(0),
"Bool" | "bool" => Self::Bool,
"String" | "string" | "str" | "Str" => Self::String,
"Array" | "array" => Self::Array(Box::new(FunctionParamType::Bool)),
"FixedBytes" | "bytes32" => Self::Array(Box::new(FunctionParamType::Bool)),
_ => {
tracing::error!(
"{}",
format!("Failed to create FunctionParamType from string: {}", string)
);
panic!("{}", format!("Failed to create FunctionParamType from string: {}", string))
}
}
}
}