use crate::convert::step_hex;
use inkpad_std::{BTreeMap, String, Vec};
use derivative::Derivative;
use parity_scale_codec::{Decode, Encode};
use parity_wasm::elements::Module;
use serde::{Deserialize, Serialize};
type Method = (String, Vec<(Option<String>, u32)>);
type MethodWithName = (String, String, Vec<(Option<String>, u32)>);
#[derive(Debug, Clone, Encode, Decode, Serialize, Deserialize)]
pub struct Metadata {
pub source: Source,
pub contract: Contract,
pub spec: Spec,
}
impl Metadata {
pub fn wasm(mut b: &[u8]) -> Option<Vec<u8>> {
let raw = step_hex(&Self::decode(&mut b).ok()?.source.wasm)?;
let mut el = Module::from_bytes(&raw).ok()?;
if el.has_names_section() {
el = match el.parse_names() {
Ok(m) => m,
Err((_, m)) => m,
}
}
el.to_bytes().ok()
}
}
impl Metadata {
pub fn messages(&self) -> BTreeMap<String, Method> {
let methods: Vec<MethodWithName> = self
.spec
.messages
.iter()
.map(|c| {
(
if c.name.is_empty() {
"".into()
} else {
c.name[0].clone()
},
c.selector.clone(),
c.args
.iter()
.map(|a| {
(
if !a.r#type.display_name.is_empty() {
Some(a.r#type.display_name[0].clone())
} else {
None
},
a.r#type.r#type,
)
})
.collect(),
)
})
.collect();
let mut map = BTreeMap::new();
for v in methods {
map.insert(v.0.clone(), (v.1.clone(), v.2));
}
map
}
pub fn constructors(&self) -> BTreeMap<String, Method> {
let methods: Vec<MethodWithName> = self
.spec
.constructors
.iter()
.map(|c| {
(
if !c.name.is_empty() {
c.name[0].clone()
} else {
"".into()
},
c.selector.clone(),
c.args
.iter()
.map(|a| {
(
if !a.r#type.display_name.is_empty() {
Some(a.r#type.display_name[0].clone())
} else {
None
},
a.r#type.r#type,
)
})
.collect(),
)
})
.collect();
let mut map = BTreeMap::new();
for v in methods {
map.insert(v.0.clone(), (v.1.clone(), v.2));
}
map
}
}
#[derive(Clone, Derivative, Deserialize, Serialize, Encode, Decode)]
#[derivative(Debug)]
pub struct Source {
pub hash: String,
#[derivative(Debug = "ignore")]
pub wasm: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
pub struct Contract {
pub name: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
pub struct Spec {
pub constructors: Vec<Constructor>,
pub messages: Vec<Message>,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
pub struct Constructor {
pub args: Vec<Arg>,
pub docs: Vec<String>,
pub name: Vec<String>,
pub selector: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
#[serde(rename_all = "camelCase")]
pub struct Message {
pub args: Vec<Arg>,
pub docs: Vec<String>,
pub mutates: bool,
pub name: Vec<String>,
pub payable: bool,
pub selector: String,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
pub struct Arg {
pub name: String,
pub r#type: Type,
}
#[derive(Clone, Debug, Deserialize, Serialize, Encode, Decode)]
#[serde(rename_all = "camelCase")]
pub struct Type {
pub display_name: Vec<String>,
pub r#type: u32,
}