From dfe0c51f65c786901a71793b555c3ec1f98fb621 Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 31 May 2024 15:01:39 -0400 Subject: [PATCH 1/3] feat: add bytearray utils to c --- Cargo.lock | 91 ++++++++++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 1 + dojo.h | 55 +++++++++++++++++++++---------- dojo.hpp | 4 +++ src/c/mod.rs | 38 ++++++++++++++++++++++ 5 files changed, 159 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c1bc5c1..0b5dbe4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -981,9 +981,9 @@ source = "git+https://github.com/cartridge-gg/cainome?rev=ec18eea5#ec18eea55a5c3 dependencies = [ "anyhow", "async-trait", - "cainome-cairo-serde", - "cainome-parser", - "cainome-rs", + "cainome-cairo-serde 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "cainome-parser 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "cainome-rs 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "cainome-rs-macro", "camino", "clap 4.5.4", @@ -998,6 +998,29 @@ dependencies = [ "url", ] +[[package]] +name = "cainome" +version = "0.2.3" +source = "git+https://github.com/cartridge-gg/cainome#b5c728a137256bc68b3645ed37734aa778c83508" +dependencies = [ + "anyhow", + "async-trait", + "cainome-cairo-serde 0.1.0 (git+https://github.com/cartridge-gg/cainome)", + "cainome-parser 0.1.0 (git+https://github.com/cartridge-gg/cainome)", + "cainome-rs 0.1.0 (git+https://github.com/cartridge-gg/cainome)", + "camino", + "clap 4.5.4", + "clap_complete", + "convert_case", + "serde", + "serde_json", + "starknet", + "thiserror", + "tracing", + "tracing-subscriber", + "url", +] + [[package]] name = "cainome-cairo-serde" version = "0.1.0" @@ -1008,6 +1031,16 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cainome-cairo-serde" +version = "0.1.0" +source = "git+https://github.com/cartridge-gg/cainome#b5c728a137256bc68b3645ed37734aa778c83508" +dependencies = [ + "serde", + "starknet", + "thiserror", +] + [[package]] name = "cainome-parser" version = "0.1.0" @@ -1021,14 +1054,45 @@ dependencies = [ "thiserror", ] +[[package]] +name = "cainome-parser" +version = "0.1.0" +source = "git+https://github.com/cartridge-gg/cainome#b5c728a137256bc68b3645ed37734aa778c83508" +dependencies = [ + "convert_case", + "quote", + "serde_json", + "starknet", + "syn 2.0.66", + "thiserror", +] + [[package]] name = "cainome-rs" version = "0.1.0" source = "git+https://github.com/cartridge-gg/cainome?rev=ec18eea5#ec18eea55a5c3c563dc502c051a8df3dfab118a9" dependencies = [ "anyhow", - "cainome-cairo-serde", - "cainome-parser", + "cainome-cairo-serde 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "cainome-parser 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "camino", + "prettyplease 0.2.19", + "proc-macro2", + "quote", + "serde_json", + "starknet", + "syn 2.0.66", + "thiserror", +] + +[[package]] +name = "cainome-rs" +version = "0.1.0" +source = "git+https://github.com/cartridge-gg/cainome#b5c728a137256bc68b3645ed37734aa778c83508" +dependencies = [ + "anyhow", + "cainome-cairo-serde 0.1.0 (git+https://github.com/cartridge-gg/cainome)", + "cainome-parser 0.1.0 (git+https://github.com/cartridge-gg/cainome)", "camino", "prettyplease 0.2.19", "proc-macro2", @@ -1045,9 +1109,9 @@ version = "0.1.0" source = "git+https://github.com/cartridge-gg/cainome?rev=ec18eea5#ec18eea55a5c3c563dc502c051a8df3dfab118a9" dependencies = [ "anyhow", - "cainome-cairo-serde", - "cainome-parser", - "cainome-rs", + "cainome-cairo-serde 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "cainome-parser 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", + "cainome-rs 0.1.0 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "proc-macro2", "quote", "serde_json", @@ -2460,7 +2524,7 @@ version = "0.7.0-alpha.5" source = "git+https://github.com/dojoengine/dojo#d9c4f4f1e3112142c6f8b80c6e88190b5a90c19d" dependencies = [ "async-trait", - "cainome", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "camino", "chrono", "convert_case", @@ -2476,6 +2540,7 @@ name = "dojo-c" version = "0.7.0-alpha.5" dependencies = [ "anyhow", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome)", "cbindgen", "crypto-bigint", "dojo-types", @@ -2553,7 +2618,7 @@ name = "dojo-types" version = "0.7.0-alpha.5" source = "git+https://github.com/dojoengine/dojo#d9c4f4f1e3112142c6f8b80c6e88190b5a90c19d" dependencies = [ - "cainome", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "crypto-bigint", "hex", "itertools 0.12.1", @@ -2572,7 +2637,7 @@ source = "git+https://github.com/dojoengine/dojo#d9c4f4f1e3112142c6f8b80c6e88190 dependencies = [ "anyhow", "async-trait", - "cainome", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "cairo-lang-filesystem", "cairo-lang-project", "cairo-lang-starknet", @@ -8444,7 +8509,7 @@ source = "git+https://github.com/dojoengine/dojo#d9c4f4f1e3112142c6f8b80c6e88190 dependencies = [ "anyhow", "async-trait", - "cainome", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "cairo-lang-compiler", "cairo-lang-defs", "cairo-lang-filesystem", @@ -9607,7 +9672,7 @@ dependencies = [ "anyhow", "async-trait", "base64 0.21.7", - "cainome", + "cainome 0.2.3 (git+https://github.com/cartridge-gg/cainome?rev=ec18eea5)", "chrono", "crypto-bigint", "dojo-types", diff --git a/Cargo.toml b/Cargo.toml index 677af7c..d4fbbb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,7 @@ futures = "0.3.30" futures-channel = "0.3.30" wasm-bindgen = "0.2.92" stream-cancel = "0.8.2" +cainome ={ git = "https://github.com/cartridge-gg/cainome" } # WASM [target.'cfg(target_arch = "wasm32")'.dependencies] diff --git a/dojo.h b/dojo.h index 3699778..71103be 100644 --- a/dojo.h +++ b/dojo.h @@ -464,6 +464,40 @@ typedef struct ResultSubscription { }; } ResultSubscription; +typedef enum ResultCArrayFieldElement_Tag { + OkCArrayFieldElement, + ErrCArrayFieldElement, +} ResultCArrayFieldElement_Tag; + +typedef struct ResultCArrayFieldElement { + ResultCArrayFieldElement_Tag tag; + union { + struct { + struct CArrayFieldElement ok; + }; + struct { + struct Error err; + }; + }; +} ResultCArrayFieldElement; + +typedef enum Resultc_char_Tag { + Okc_char, + Errc_char, +} Resultc_char_Tag; + +typedef struct Resultc_char { + Resultc_char_Tag tag; + union { + struct { + const char *ok; + }; + struct { + struct Error err; + }; + }; +} Resultc_char; + typedef enum ResultFieldElement_Tag { OkFieldElement, ErrFieldElement, @@ -532,23 +566,6 @@ typedef struct ResultAccount { }; } ResultAccount; -typedef enum ResultCArrayFieldElement_Tag { - OkCArrayFieldElement, - ErrCArrayFieldElement, -} ResultCArrayFieldElement_Tag; - -typedef struct ResultCArrayFieldElement { - ResultCArrayFieldElement_Tag tag; - union { - struct { - struct CArrayFieldElement ok; - }; - struct { - struct Error err; - }; - }; -} ResultCArrayFieldElement; - typedef struct Call { const char *to; const char *selector; @@ -629,6 +646,10 @@ struct Resultbool client_remove_models_to_sync(struct ToriiClient *client, const struct KeysClause *models, uintptr_t models_len); +struct ResultCArrayFieldElement bytearray_serialize(const char *str); + +struct Resultc_char bytearray_deserialize(const struct FieldElement *felts, uintptr_t felts_len); + struct ResultFieldElement typed_data_encode(const char *typed_data, struct FieldElement address); struct FieldElement signing_key_new(void); diff --git a/dojo.hpp b/dojo.hpp index 92fdfc7..fce8457 100644 --- a/dojo.hpp +++ b/dojo.hpp @@ -831,6 +831,10 @@ Result client_remove_models_to_sync(ToriiClient *client, const KeysClause *models, uintptr_t models_len); +Result> bytearray_serialize(const char *str); + +Result bytearray_deserialize(const FieldElement *felts, uintptr_t felts_len); + Result typed_data_encode(const char *typed_data, FieldElement address); FieldElement signing_key_new(); diff --git a/src/c/mod.rs b/src/c/mod.rs index 9c5f9a1..6310004 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -7,6 +7,7 @@ use self::types::{ use crate::constants; use crate::types::{Account, Provider, Subscription}; use crate::utils::watch_tx; +use cainome::cairo_serde::{self, ByteArray, CairoSerde}; use starknet::accounts::{Account as StarknetAccount, ExecutionEncoding, SingleOwnerAccount}; use starknet::core::types::FunctionCall; use starknet::core::utils::{ @@ -329,6 +330,43 @@ pub unsafe extern "C" fn client_remove_models_to_sync( } } +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn bytearray_serialize( + str: *const c_char, +) -> Result> { + let str = unsafe { CStr::from_ptr(str).to_string_lossy().into_owned() }; + let bytearray = match ByteArray::from_string(str.as_str()) { + Ok(bytearray) => bytearray, + Err(e) => return Result::Err(e.into()), + }; + + let felts = cairo_serde::ByteArray::cairo_serialize(&bytearray); + let felts = felts.iter().map(|f| f.into()).collect::>(); + Result::Ok(felts.into()) +} + +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn bytearray_deserialize( + felts: *const types::FieldElement, + felts_len: usize, +) -> Result<*const c_char> { + let felts = unsafe { std::slice::from_raw_parts(felts, felts_len) }; + let felts = felts.iter().map(|f| (&f.clone()).into()).collect::>(); + let bytearray = match cairo_serde::ByteArray::cairo_deserialize(&felts, 0) { + Ok(bytearray) => bytearray, + Err(e) => return Result::Err(e.into()), + }; + + let bytearray = match bytearray.to_string() { + Ok(bytearray) => bytearray, + Err(e) => return Result::Err(e.into()), + }; + + Result::Ok(CString::new(bytearray).unwrap().into_raw()) +} + #[no_mangle] #[allow(clippy::missing_safety_doc)] pub unsafe extern "C" fn typed_data_encode( From aedff9228a1a80649a902a7b87b2c07183bf5052 Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 31 May 2024 15:08:49 -0400 Subject: [PATCH 2/3] feat: add bytearray utils to wasm --- src/wasm/mod.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index 97ca868..a18a563 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -3,6 +3,7 @@ mod utils; use std::str::FromStr; use std::sync::Arc; +use cainome::cairo_serde::{self, ByteArray, CairoSerde}; use crypto_bigint::U256; use futures::StreamExt; use js_sys::Array; @@ -658,6 +659,36 @@ pub fn hash_get_contract_address( Ok(format!("{:#x}", address)) } +#[wasm_bindgen(js_name = byteArraySerialize)] +pub fn bytearray_serialize(str: &str) -> Result, JsValue> { + let bytearray = match ByteArray::from_string(str) { + Ok(bytearray) => bytearray, + Err(e) => return Err(JsValue::from(format!("failed to parse bytearray: {e}"))), + }; + let felts = cairo_serde::ByteArray::cairo_serialize(&bytearray); + + Ok(felts.iter().map(|f| format!("{:#x}", f)).collect()) +} + +#[wasm_bindgen(js_name = byteArrayDeserialize)] +pub fn bytearray_deserialize(felts: Vec) -> Result { + let felts = felts + .into_iter() + .map(|f| FieldElement::from_str(f.as_str())) + .collect::, _>>() + .map_err(|e| JsValue::from(format!("failed to parse felts: {e}")))?; + + let bytearray = match cairo_serde::ByteArray::cairo_deserialize(&felts, 0) { + Ok(bytearray) => bytearray, + Err(e) => return Err(JsValue::from(format!("failed to deserialize bytearray: {e}"))), + }; + + match bytearray.to_string() { + Ok(s) => Ok(s), + Err(e) => Err(JsValue::from(format!("failed to serialize bytearray: {e}"))), + } +} + #[wasm_bindgen] impl Client { #[wasm_bindgen(js_name = getEntities)] From 149c24841333f724900b32850ba4850871aa9e46 Mon Sep 17 00:00:00 2001 From: Nasr Date: Fri, 31 May 2024 15:09:08 -0400 Subject: [PATCH 3/3] fmt --- src/c/mod.rs | 10 ++++++++-- src/wasm/mod.rs | 8 ++++++-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/c/mod.rs b/src/c/mod.rs index 6310004..3a1f6c4 100644 --- a/src/c/mod.rs +++ b/src/c/mod.rs @@ -342,7 +342,10 @@ pub unsafe extern "C" fn bytearray_serialize( }; let felts = cairo_serde::ByteArray::cairo_serialize(&bytearray); - let felts = felts.iter().map(|f| f.into()).collect::>(); + let felts = felts + .iter() + .map(|f| f.into()) + .collect::>(); Result::Ok(felts.into()) } @@ -353,7 +356,10 @@ pub unsafe extern "C" fn bytearray_deserialize( felts_len: usize, ) -> Result<*const c_char> { let felts = unsafe { std::slice::from_raw_parts(felts, felts_len) }; - let felts = felts.iter().map(|f| (&f.clone()).into()).collect::>(); + let felts = felts + .iter() + .map(|f| (&f.clone()).into()) + .collect::>(); let bytearray = match cairo_serde::ByteArray::cairo_deserialize(&felts, 0) { Ok(bytearray) => bytearray, Err(e) => return Result::Err(e.into()), diff --git a/src/wasm/mod.rs b/src/wasm/mod.rs index a18a563..777c362 100644 --- a/src/wasm/mod.rs +++ b/src/wasm/mod.rs @@ -680,14 +680,18 @@ pub fn bytearray_deserialize(felts: Vec) -> Result { let bytearray = match cairo_serde::ByteArray::cairo_deserialize(&felts, 0) { Ok(bytearray) => bytearray, - Err(e) => return Err(JsValue::from(format!("failed to deserialize bytearray: {e}"))), + Err(e) => { + return Err(JsValue::from(format!( + "failed to deserialize bytearray: {e}" + ))) + } }; match bytearray.to_string() { Ok(s) => Ok(s), Err(e) => Err(JsValue::from(format!("failed to serialize bytearray: {e}"))), } -} +} #[wasm_bindgen] impl Client {