Skip to content

Commit

Permalink
feat: 🎸 add u256 and event decode and encode
Browse files Browse the repository at this point in the history
BREAKING CHANGE: 🧨 y
  • Loading branch information
YancyParker committed Mar 7, 2024
1 parent ad642db commit 6ae5697
Show file tree
Hide file tree
Showing 9 changed files with 559 additions and 50 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "ola-lang-abi"
version = "1.0.5"
version = "1.0.6"
edition = "2021"
license = "MIT"
description = "Ola Smart Contract ABI parsing library"
Expand All @@ -16,7 +16,7 @@ nom = { version = "7.1.3", default-features = false, features = ["std"] }
serde = { version = "1.0.193", default-features = false, features = ["derive"] }
serde_json = { version = "1.0.108", default-features = false, features = ["std"] }
tiny-keccak = { version = "2.0", default-features = false, features = ["keccak"] }

mini-goldilocks = { git = "https://github.com/Sin7Y/mini-goldilocks", branch = "main" }
[dev-dependencies]
pretty_assertions = "1.0"
rand = "0.8"
66 changes: 43 additions & 23 deletions examples/BookExample.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,30 +5,29 @@
"inputs": [
{
"name": "id",
"type": "u32",
"internalType": "u32"
"type": "u32"
},
{
"name": "name",
"type": "string",
"internalType": "string"
"type": "string"
}
],
"outputs": [
{
"name": "",
"type": "tuple",
"internalType": "struct BookExample.Book",
"components": [
{
"name": "book_id",
"type": "u32",
"internalType": "u32"
"type": "u32"
},
{
"name": "book_name",
"type": "string",
"internalType": "string"
"type": "string"
},
{
"name": "author",
"type": "string"
}
]
}
Expand All @@ -41,26 +40,26 @@
{
"name": "_book",
"type": "tuple",
"internalType": "struct BookExample.Book",
"components": [
{
"name": "book_id",
"type": "u32",
"internalType": "u32"
"type": "u32"
},
{
"name": "book_name",
"type": "string",
"internalType": "string"
"type": "string"
},
{
"name": "author",
"type": "string"
}
]
}
],
"outputs": [
{
"name": "",
"type": "string",
"internalType": "string"
"type": "string"
}
]
},
Expand All @@ -71,27 +70,48 @@
{
"name": "_book",
"type": "tuple",
"internalType": "struct BookExample.Book",
"components": [
{
"name": "book_id",
"type": "u32",
"internalType": "u32"
"type": "u32"
},
{
"name": "book_name",
"type": "string",
"internalType": "string"
"type": "string"
},
{
"name": "author",
"type": "string"
}
]
}
],
"outputs": [
{
"name": "",
"type": "u32",
"internalType": "u32"
"type": "u32"
}
]
},
{
"name": "BookCreated",
"type": "event",
"inputs": [
{
"name": "id",
"type": "u32",
"indexed": true
},
{
"name": "name",
"type": "string",
"indexed": true
},
{
"name": "author",
"type": "string"
}
],
"anonymous": false
}
]
37 changes: 37 additions & 0 deletions examples/log_data.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::fs::File;

use ola_lang_abi::{Abi, FixedArray4};

fn main() {
// Parse ABI JSON file
let abi: Abi = {
let file = File::open("examples/BookExample.json").expect("failed to open ABI file");

serde_json::from_reader(file).expect("failed to parse ABI")
};

let topics = vec![
FixedArray4([
876009939773297099,
9423535973325601276,
68930750687700470,
16776232995860792718,
]),
FixedArray4([0, 0, 0, 10]),
FixedArray4([
1298737262017568572,
12445360621592034485,
13004999764278192581,
3441866816748036873,
]),
];

let data = vec![5, 104, 101, 108, 108, 111];

// Decode
let (evt, decoded_data) = abi
.decode_log_from_slice(&topics, &data)
.expect("failed decoding log");

println!("event: {}\ndata: {:?}", evt.name, decoded_data);
}
66 changes: 64 additions & 2 deletions src/abi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use anyhow::{anyhow, Result};
use serde::{de::Visitor, Deserialize, Serialize};

use crate::{params::Param, DecodedParams, Value};
use crate::{params::Param, DecodedParams, Event, FixedArray4, Value};

/// Contract ABI (Abstract Binary Interface).
///
Expand All @@ -22,6 +22,8 @@ use crate::{params::Param, DecodedParams, Value};
pub struct Abi {
/// Contract defined functions.
pub functions: Vec<Function>,

pub events: Vec<Event>,
}

impl Abi {
Expand Down Expand Up @@ -62,6 +64,27 @@ impl Abi {
Ok((f, decoded_params))
}

/// Decode event data from slice.
pub fn decode_log_from_slice<'a>(
&'a self,
topics: &[FixedArray4],
data: &[u64],
) -> Result<(&'a Event, DecodedParams)> {
if topics.is_empty() {
return Err(anyhow!("missing event topic id"));
}

let e = self
.events
.iter()
.find(|e| e.topic() == topics[0])
.ok_or_else(|| anyhow!("ABI event not found"))?;

let decoded_params = e.decode_data_from_slice(topics, data)?;

Ok((e, decoded_params))
}

pub fn encode_input_with_signature(
&self,
signature: &str,
Expand Down Expand Up @@ -101,6 +124,17 @@ impl Serialize for Abi {
name: Some(f.name.clone()),
inputs: Some(f.inputs.clone()),
outputs: Some(f.outputs.clone()),
anonymous: None,
});
}

for e in &self.events {
entries.push(AbiEntry {
type_: String::from("event"),
name: Some(e.name.clone()),
inputs: Some(e.inputs.clone()),
outputs: None,
anonymous: Some(e.anonymous),
});
}
entries.serialize(serializer)
Expand Down Expand Up @@ -198,6 +232,8 @@ struct AbiEntry {
inputs: Option<Vec<Param>>,
#[serde(skip_serializing_if = "Option::is_none")]
outputs: Option<Vec<Param>>,
#[serde(skip_serializing_if = "Option::is_none")]
anonymous: Option<bool>,
}

struct AbiVisitor;
Expand All @@ -213,7 +249,10 @@ impl<'de> Visitor<'de> for AbiVisitor {
where
A: serde::de::SeqAccess<'de>,
{
let mut abi = Abi { functions: vec![] };
let mut abi = Abi {
functions: vec![],
events: vec![],
};

loop {
let entry = seq.next_element::<AbiEntry>()?;
Expand All @@ -237,6 +276,23 @@ impl<'de> Visitor<'de> for AbiVisitor {
outputs,
});
}
"event" => {
let inputs = entry.inputs.unwrap_or_default();

let name = entry.name.ok_or_else(|| {
serde::de::Error::custom("missing function name".to_string())
})?;

let anonymous = entry.anonymous.ok_or_else(|| {
serde::de::Error::custom("missing event anonymous field".to_string())
})?;

abi.events.push(Event {
name,
inputs,
anonymous,
});
}

_ => {
return Err(serde::de::Error::custom(format!(
Expand Down Expand Up @@ -334,10 +390,12 @@ mod test {
Param {
name: "".to_string(),
type_: Type::Address,
indexed: None,
},
Param {
name: "x".to_string(),
type_: Type::FixedArray(Box::new(Type::U32), 2),
indexed: None,
},
],
outputs: vec![],
Expand Down Expand Up @@ -370,6 +428,7 @@ mod test {
let fun = test_function();
let abi = Abi {
functions: vec![fun],
events: vec![],
};

let mut params = Value::encode(&input_values);
Expand Down Expand Up @@ -436,17 +495,20 @@ mod test {
Param {
name: "n".to_string(),
type_: Type::U32,
indexed: None,
},
Param {
name: "x".to_string(),
type_: Type::Tuple(vec![
("a".to_string(), Type::U32),
("b".to_string(), Type::String)
]),
indexed: None,
}
],
outputs: vec![],
}],
events: vec![],
}
);
}
Expand Down
Loading

0 comments on commit 6ae5697

Please sign in to comment.