From ada71b67a6ed9b0bb6408c4e3833b88387d4da5d Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 13:17:41 +0700 Subject: [PATCH 01/13] refactor(typed-data): parse number string macro --- crates/torii/libp2p/src/typed_data.rs | 32 ++++++++++++++++++--------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/crates/torii/libp2p/src/typed_data.rs b/crates/torii/libp2p/src/typed_data.rs index b15ee88188..acd170f5e0 100644 --- a/crates/torii/libp2p/src/typed_data.rs +++ b/crates/torii/libp2p/src/typed_data.rs @@ -444,6 +444,16 @@ impl Domain { } } +macro_rules! from_str { + ($string:expr, $type:ty) => { + if $string.starts_with("0x") || $string.starts_with("0X") { + <$type>::from_str_radix(&$string[2..], 16) + } else { + <$type>::from_str($string) + }.map_err(|e| Error::InvalidMessageError(format!("Failed to parse number: {}", e))) + }; +} + pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error> { match value { PrimitiveType::Object(object) => match ty { @@ -581,37 +591,37 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error PrimitiveType::String(string) => match ty { Ty::Primitive(primitive) => match primitive { Primitive::I8(v) => { - *v = Some(i8::from_str(string).unwrap()); + *v = Some(from_str!(string, i8)?); } Primitive::I16(v) => { - *v = Some(i16::from_str(string).unwrap()); + *v = Some(from_str!(string, i16)?); } Primitive::I32(v) => { - *v = Some(i32::from_str(string).unwrap()); + *v = Some(from_str!(string, i32)?); } Primitive::I64(v) => { - *v = Some(i64::from_str(string).unwrap()); + *v = Some(from_str!(string, i64)?); } Primitive::I128(v) => { - *v = Some(i128::from_str(string).unwrap()); + *v = Some(from_str!(string, i128)?); } Primitive::U8(v) => { - *v = Some(u8::from_str(string).unwrap()); + *v = Some(from_str!(string, u8)?); } Primitive::U16(v) => { - *v = Some(u16::from_str(string).unwrap()); + *v = Some(from_str!(string, u16)?); } Primitive::U32(v) => { - *v = Some(u32::from_str(string).unwrap()); + *v = Some(from_str!(string, u32)?); } Primitive::U64(v) => { - *v = Some(u64::from_str(string).unwrap()); + *v = Some(from_str!(string, u64)?); } Primitive::U128(v) => { - *v = Some(u128::from_str(string).unwrap()); + *v = Some(from_str!(string, u128)?); } Primitive::USize(v) => { - *v = Some(u32::from_str(string).unwrap()); + *v = Some(from_str!(string, u32)?); } Primitive::Felt252(v) => { *v = Some(Felt::from_str(string).unwrap()); From f1c5b4b2a99e1535c89261d0f4d45387f927a6b3 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 13:20:21 +0700 Subject: [PATCH 02/13] fmt --- crates/torii/libp2p/src/typed_data.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/torii/libp2p/src/typed_data.rs b/crates/torii/libp2p/src/typed_data.rs index acd170f5e0..e1debbd41e 100644 --- a/crates/torii/libp2p/src/typed_data.rs +++ b/crates/torii/libp2p/src/typed_data.rs @@ -450,7 +450,8 @@ macro_rules! from_str { <$type>::from_str_radix(&$string[2..], 16) } else { <$type>::from_str($string) - }.map_err(|e| Error::InvalidMessageError(format!("Failed to parse number: {}", e))) + } + .map_err(|e| Error::InvalidMessageError(format!("Failed to parse number: {}", e))) }; } From a45f97f7885f83a92351eec03d4ab1319607b5bb Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 13:50:20 +0700 Subject: [PATCH 03/13] refactor(libp2p): modularize & client server features --- Cargo.lock | 22 +++- Cargo.toml | 1 + bin/torii/Cargo.toml | 2 +- crates/torii/client/Cargo.toml | 2 +- crates/torii/client/src/client/error.rs | 2 +- crates/torii/libp2p/Cargo.toml | 11 +- crates/torii/libp2p/src/client/mod.rs | 2 +- .../torii/libp2p/src/{errors.rs => error.rs} | 11 +- crates/torii/libp2p/src/lib.rs | 14 ++- crates/torii/libp2p/src/server/mod.rs | 6 +- crates/torii/libp2p/src/{tests.rs => test.rs} | 11 +- crates/torii/libp2p/src/types.rs | 2 +- crates/torii/typed-data/Cargo.toml | 23 ++++ crates/torii/typed-data/src/error.rs | 37 ++++++ crates/torii/typed-data/src/lib.rs | 6 + .../{libp2p => typed-data}/src/typed_data.rs | 108 ++++++++---------- 16 files changed, 170 insertions(+), 90 deletions(-) rename crates/torii/libp2p/src/{errors.rs => error.rs} (91%) rename crates/torii/libp2p/src/{tests.rs => test.rs} (99%) create mode 100644 crates/torii/typed-data/Cargo.toml create mode 100644 crates/torii/typed-data/src/error.rs create mode 100644 crates/torii/typed-data/src/lib.rs rename crates/torii/{libp2p => typed-data}/src/typed_data.rs (92%) diff --git a/Cargo.lock b/Cargo.lock index 18f04e4d07..06b9191a7f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15870,7 +15870,6 @@ name = "torii-relay" version = "1.0.9" dependencies = [ "anyhow", - "cainome 0.4.11", "chrono", "crypto-bigint", "dojo-types 1.0.9", @@ -15885,13 +15884,12 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", - "sqlx", "starknet 0.12.0", "starknet-crypto 0.7.2", "tempfile", "thiserror 1.0.63", "tokio", - "torii-core", + "torii-typed-data", "tracing", "tracing-subscriber", "tracing-wasm", @@ -15934,6 +15932,24 @@ dependencies = [ "warp", ] +[[package]] +name = "torii-typed-data" +version = "1.0.9" +dependencies = [ + "anyhow", + "chrono", + "crypto-bigint", + "dojo-types 1.0.9", + "dojo-world", + "indexmap 2.5.0", + "serde", + "serde_json", + "starknet 0.12.0", + "starknet-crypto 0.7.2", + "thiserror 1.0.63", + "tracing", +] + [[package]] name = "tower" version = "0.4.13" diff --git a/Cargo.toml b/Cargo.toml index 9dc1b2bddc..baf01ea3dd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -124,6 +124,7 @@ torii-graphql = { path = "crates/torii/graphql" } torii-grpc = { path = "crates/torii/grpc" } torii-relay = { path = "crates/torii/libp2p" } torii-server = { path = "crates/torii/server" } +torii-typed-data = { path = "crates/torii/typed-data" } # saya saya-core = { path = "crates/saya/core" } diff --git a/bin/torii/Cargo.toml b/bin/torii/Cargo.toml index efa4339e0a..daae76922e 100644 --- a/bin/torii/Cargo.toml +++ b/bin/torii/Cargo.toml @@ -39,7 +39,7 @@ torii-cli.workspace = true torii-core.workspace = true torii-graphql.workspace = true torii-grpc = { workspace = true, features = [ "server" ] } -torii-relay.workspace = true +torii-relay = { workspace = true, features = [ "server" ] } torii-server.workspace = true tower.workspace = true diff --git a/crates/torii/client/Cargo.toml b/crates/torii/client/Cargo.toml index d534123d07..fa5d6debf8 100644 --- a/crates/torii/client/Cargo.toml +++ b/crates/torii/client/Cargo.toml @@ -21,7 +21,7 @@ starknet-crypto.workspace = true thiserror.workspace = true tokio = { version = "1.32.0", features = [ "sync" ], default-features = false } torii-grpc = { workspace = true, features = [ "client" ] } -torii-relay = { workspace = true } +torii-relay = { workspace = true, features = [ "client" ] } url.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/crates/torii/client/src/client/error.rs b/crates/torii/client/src/client/error.rs index 5a036e19cd..734c068707 100644 --- a/crates/torii/client/src/client/error.rs +++ b/crates/torii/client/src/client/error.rs @@ -16,7 +16,7 @@ pub enum Error { #[error(transparent)] GrpcClient(#[from] torii_grpc::client::Error), #[error(transparent)] - RelayClient(#[from] torii_relay::errors::Error), + RelayClient(#[from] torii_relay::error::Error), #[error(transparent)] Model(#[from] ModelError), #[error("Unsupported query")] diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index 05cf945115..a60070639f 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -5,6 +5,11 @@ name = "torii-relay" repository.workspace = true version.workspace = true +[features] +client = [ ] +default = [ "server" ] +server = [ "dep:sqlx", "dep:torii-core" ] + # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] @@ -13,16 +18,16 @@ rand.workspace = true serde.workspace = true # preserve order anyhow.workspace = true -cainome.workspace = true chrono.workspace = true crypto-bigint.workspace = true dojo-types.workspace = true dojo-world.workspace = true indexmap.workspace = true serde_json.workspace = true -starknet-crypto.workspace = true starknet.workspace = true +starknet-crypto.workspace = true thiserror.workspace = true +torii-typed-data.workspace = true tracing.workspace = true [dev-dependencies] @@ -34,8 +39,6 @@ tracing-subscriber.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libp2p = { git = "https://github.com/libp2p/rust-libp2p", features = [ "dns", "ed25519", "gossipsub", "identify", "macros", "noise", "ping", "quic", "relay", "tcp", "tokio", "websocket", "yamux" ], rev = "cdc9638" } libp2p-webrtc = { git = "https://github.com/libp2p/rust-libp2p", features = [ "pem", "tokio" ], rev = "cdc9638" } -sqlx.workspace = true -torii-core.workspace = true [target.'cfg(target_arch = "wasm32")'.dependencies] libp2p = { git = "https://github.com/libp2p/rust-libp2p", features = [ "ed25519", "gossipsub", "identify", "macros", "noise", "ping", "tcp", "wasm-bindgen", "yamux" ], rev = "cdc9638" } diff --git a/crates/torii/libp2p/src/client/mod.rs b/crates/torii/libp2p/src/client/mod.rs index f438d23072..eb5e66bb18 100644 --- a/crates/torii/libp2p/src/client/mod.rs +++ b/crates/torii/libp2p/src/client/mod.rs @@ -17,7 +17,7 @@ use tracing::info; pub mod events; use crate::client::events::ClientEvent; use crate::constants; -use crate::errors::Error; +use crate::error::Error; use crate::types::Message; pub(crate) const LOG_TARGET: &str = "torii::relay::client"; diff --git a/crates/torii/libp2p/src/errors.rs b/crates/torii/libp2p/src/error.rs similarity index 91% rename from crates/torii/libp2p/src/errors.rs rename to crates/torii/libp2p/src/error.rs index ec615b88d7..9326c290a4 100644 --- a/crates/torii/libp2p/src/errors.rs +++ b/crates/torii/libp2p/src/error.rs @@ -7,6 +7,8 @@ use libp2p::noise; use starknet::providers::ProviderError; use thiserror::Error; +use torii_typed_data::error::Error as TypedDataError; + #[derive(Error, Debug)] pub enum Error { #[error(transparent)] @@ -41,12 +43,15 @@ pub enum Error { #[error("Failed to read certificate: {0}")] ReadCertificateError(anyhow::Error), - #[error("Invalid message provided: {0}")] - InvalidMessageError(String), - #[error("Invalid type provided: {0}")] InvalidTypeError(String), #[error(transparent)] ProviderError(#[from] ProviderError), + + #[error(transparent)] + TypedDataError(#[from] TypedDataError), + + #[error("Invalid message provided: {0}")] + InvalidMessageError(String), } diff --git a/crates/torii/libp2p/src/lib.rs b/crates/torii/libp2p/src/lib.rs index 9d08de68c6..ec95bd8724 100644 --- a/crates/torii/libp2p/src/lib.rs +++ b/crates/torii/libp2p/src/lib.rs @@ -1,10 +1,14 @@ #![warn(unused_crate_dependencies)] -pub mod client; mod constants; -pub mod errors; -#[cfg(not(target_arch = "wasm32"))] +pub mod error; + +#[cfg(feature = "client")] +pub mod client; +#[cfg(feature = "server")] pub mod server; -mod tests; -pub mod typed_data; + +#[cfg(test)] +mod test; + pub mod types; diff --git a/crates/torii/libp2p/src/server/mod.rs b/crates/torii/libp2p/src/server/mod.rs index 7bb0508cc8..56d6e8df89 100644 --- a/crates/torii/libp2p/src/server/mod.rs +++ b/crates/torii/libp2p/src/server/mod.rs @@ -32,13 +32,13 @@ use tracing::{info, warn}; use webrtc::tokio::Certificate; use crate::constants; -use crate::errors::Error; +use crate::error::Error; mod events; use crate::server::events::ServerEvent; -use crate::typed_data::{parse_value_to_ty, PrimitiveType, TypedData}; use crate::types::Message; +use torii_typed_data::typed_data::{parse_value_to_ty, PrimitiveType, TypedData}; pub(crate) const LOG_TARGET: &str = "torii::relay::server"; @@ -128,7 +128,7 @@ impl Relay

{ relay: relay::Behaviour::new(key.public().to_peer_id(), Default::default()), ping: ping::Behaviour::new(ping::Config::new()), identify: identify::Behaviour::new(identify::Config::new( - format!("/torii-relay/{}", env!("CARGO_PKG_VERSION")), + format!("/{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")), key.public(), )), gossipsub: gossipsub::Behaviour::new( diff --git a/crates/torii/libp2p/src/tests.rs b/crates/torii/libp2p/src/test.rs similarity index 99% rename from crates/torii/libp2p/src/tests.rs rename to crates/torii/libp2p/src/test.rs index 9016f053ba..c8c18671e9 100644 --- a/crates/torii/libp2p/src/tests.rs +++ b/crates/torii/libp2p/src/test.rs @@ -1,9 +1,7 @@ -#[cfg(test)] -mod test { use std::error::Error; use crate::client::RelayClient; - use crate::typed_data::{ + use torii_typed_data::typed_data::{ map_ty_to_primitive, parse_value_to_ty, Domain, PrimitiveType, TypedData, }; @@ -545,7 +543,7 @@ mod test { use torii_core::types::{Contract, ContractType}; use crate::server::Relay; - use crate::typed_data::{Domain, Field, SimpleField, TypedData}; + use torii_typed_data::typed_data::{Domain, Field, SimpleField, TypedData}; use crate::types::Message; let _ = tracing_subscriber::fmt() @@ -677,12 +675,12 @@ mod test { ); typed_data.message.insert( "identity".to_string(), - crate::typed_data::PrimitiveType::String(account.address.to_string()), + torii_typed_data::typed_data::PrimitiveType::String(account.address.to_string()), ); typed_data.message.insert( "message".to_string(), - crate::typed_data::PrimitiveType::String("mimi".to_string()), + torii_typed_data::typed_data::PrimitiveType::String("mimi".to_string()), ); let message_hash = typed_data.encode(account.address).unwrap(); @@ -752,4 +750,3 @@ mod test { } } } -} diff --git a/crates/torii/libp2p/src/types.rs b/crates/torii/libp2p/src/types.rs index 1122f046fe..ff6ae7ecef 100644 --- a/crates/torii/libp2p/src/types.rs +++ b/crates/torii/libp2p/src/types.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use starknet::core::types::Felt; -use crate::typed_data::TypedData; +use torii_typed_data::TypedData; #[derive(Debug, Clone, Serialize, Deserialize)] pub struct Message { diff --git a/crates/torii/typed-data/Cargo.toml b/crates/torii/typed-data/Cargo.toml new file mode 100644 index 0000000000..2d5e621f98 --- /dev/null +++ b/crates/torii/typed-data/Cargo.toml @@ -0,0 +1,23 @@ +[package] +edition.workspace = true +license-file.workspace = true +name = "torii-typed-data" +repository.workspace = true +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +serde.workspace = true +# preserve order +anyhow.workspace = true +chrono.workspace = true +crypto-bigint.workspace = true +dojo-types.workspace = true +dojo-world.workspace = true +indexmap.workspace = true +serde_json.workspace = true +starknet-crypto.workspace = true +starknet.workspace = true +thiserror.workspace = true +tracing.workspace = true \ No newline at end of file diff --git a/crates/torii/typed-data/src/error.rs b/crates/torii/typed-data/src/error.rs new file mode 100644 index 0000000000..28a09c2986 --- /dev/null +++ b/crates/torii/typed-data/src/error.rs @@ -0,0 +1,37 @@ +use thiserror::Error; + +#[derive(Error, Debug)] +pub enum Error { + #[error("Invalid type: {0}")] + InvalidType(String), + + #[error("Type not found: {0}")] + TypeNotFound(String), + + #[error("Invalid enum: {0}")] + InvalidEnum(String), + + #[error("Invalid field: {0}")] + InvalidField(String), + + #[error("Invalid value: {0}")] + InvalidValue(String), + + #[error("Invalid domain: {0}")] + InvalidDomain(String), + + #[error("Invalid message: {0}")] + InvalidMessage(String), + + #[error("Serialization error: {0}")] + SerializationError(#[from] serde_json::Error), + + #[error("Crypto error: {0}")] + CryptoError(String), + + #[error("Parse error: {0}")] + ParseError(String), + + #[error("Field not found: {0}")] + FieldNotFound(String), +} diff --git a/crates/torii/typed-data/src/lib.rs b/crates/torii/typed-data/src/lib.rs new file mode 100644 index 0000000000..9b69d5d25a --- /dev/null +++ b/crates/torii/typed-data/src/lib.rs @@ -0,0 +1,6 @@ +#![warn(unused_crate_dependencies)] + +pub mod error; +pub mod typed_data; + +pub use typed_data::TypedData; diff --git a/crates/torii/libp2p/src/typed_data.rs b/crates/torii/typed-data/src/typed_data.rs similarity index 92% rename from crates/torii/libp2p/src/typed_data.rs rename to crates/torii/typed-data/src/typed_data.rs index e1debbd41e..a28308ad45 100644 --- a/crates/torii/libp2p/src/typed_data.rs +++ b/crates/torii/typed-data/src/typed_data.rs @@ -11,7 +11,7 @@ use starknet::core::types::Felt; use starknet::core::utils::{cairo_short_string_to_felt, get_selector_from_name}; use starknet_crypto::poseidon_hash_many; -use crate::errors::Error; +use crate::error::Error; #[derive(Clone, Debug, Serialize, Deserialize)] pub struct SimpleField { @@ -93,11 +93,7 @@ fn get_preset_types() -> IndexMap> { // Looks up both the types hashmap as well as the preset types // Returns the fields and the hashmap of types fn get_fields(name: &str, types: &IndexMap>) -> Result, Error> { - if let Some(fields) = types.get(name) { - return Ok(fields.clone()); - } - - Err(Error::InvalidMessageError(format!("Type {} not found", name))) + types.get(name).cloned().ok_or_else(|| Error::TypeNotFound(name.to_string())) } fn get_dependencies( @@ -234,17 +230,15 @@ pub(crate) fn get_value_type( } } - Err(Error::InvalidMessageError(format!("Field {} not found in types", name))) + Err(Error::FieldNotFound(name.to_string())) } fn get_hex(value: &str) -> Result { - if let Ok(felt) = Felt::from_str(value) { - Ok(felt) - } else { - // assume its a short string and encode - cairo_short_string_to_felt(value) - .map_err(|e| Error::InvalidMessageError(format!("Invalid shortstring for felt: {}", e))) - } + Felt::from_str(value) + .or_else(|_| { + cairo_short_string_to_felt(value) + .map_err(|e| Error::ParseError(format!("Invalid shortstring for felt: {}", e))) + }) } impl PrimitiveType { @@ -262,9 +256,9 @@ impl PrimitiveType { let mut hashes = Vec::new(); if ctx.base_type == "enum" { - let (variant_name, value) = obj.first().ok_or_else(|| { - Error::InvalidMessageError("Enum value must be populated".to_string()) - })?; + let (variant_name, value) = obj.first() + .ok_or_else(|| Error::InvalidEnum("Enum value must be populated".to_string()))?; + let variant_type = get_value_type(variant_name, types)?; // variant index @@ -282,9 +276,7 @@ impl PrimitiveType { .split(',') .nth(idx) .ok_or_else(|| { - Error::InvalidMessageError( - "Invalid enum variant type".to_string(), - ) + Error::InvalidEnum("Invalid enum variant type".to_string()) })?; let field_hash = @@ -306,7 +298,7 @@ impl PrimitiveType { let type_hash = encode_type(r#type, if ctx.is_preset { preset_types } else { types })?; hashes.push(get_selector_from_name(&type_hash).map_err(|e| { - Error::InvalidMessageError(format!( + Error::ParseError(format!( "Invalid type {} for selector: {}", r#type, e )) @@ -339,9 +331,7 @@ impl PrimitiveType { .collect::>(); if inner_types.len() != array.len() { - return Err(Error::InvalidMessageError( - "Tuple length mismatch".to_string(), - )); + return Err(Error::InvalidValue("Tuple length mismatch".to_string())); } let mut hashes = Vec::new(); @@ -371,7 +361,7 @@ impl PrimitiveType { "string" => { // split the string into short strings and encode let byte_array = ByteArray::from_string(string).map_err(|e| { - Error::InvalidMessageError(format!("Invalid string for bytearray: {}", e)) + Error::ParseError(format!("Invalid string for bytearray: {}", e)) })?; let mut hashes = vec![Felt::from(byte_array.data.len())]; @@ -386,18 +376,18 @@ impl PrimitiveType { Ok(poseidon_hash_many(hashes.as_slice())) } "selector" => get_selector_from_name(string) - .map_err(|e| Error::InvalidMessageError(format!("Invalid selector: {}", e))), + .map_err(|e| Error::ParseError(format!("Invalid selector: {}", e))), "felt" => get_hex(string), "ContractAddress" => get_hex(string), "ClassHash" => get_hex(string), "timestamp" => get_hex(string), "u128" => get_hex(string), "i128" => get_hex(string), - _ => Err(Error::InvalidMessageError(format!("Invalid type {} for string", r#type))), + _ => Err(Error::InvalidType(format!("Invalid type {} for string", r#type))), }, PrimitiveType::Number(number) => { let felt = Felt::from_str(&number.to_string()).map_err(|_| { - Error::InvalidMessageError(format!("Invalid number {}", number)) + Error::ParseError(format!("Invalid number {}", number)) })?; Ok(felt) } @@ -425,16 +415,21 @@ impl Domain { } pub fn encode(&self, types: &IndexMap>) -> Result { - let mut object = IndexMap::new(); + if self.revision.as_deref().unwrap_or("1") != "1" { + return Err(Error::InvalidDomain( + "Legacy revision 0 is not supported".to_string() + )); + } + let mut object = IndexMap::new(); object.insert("name".to_string(), PrimitiveType::String(self.name.clone())); object.insert("version".to_string(), PrimitiveType::String(self.version.clone())); object.insert("chainId".to_string(), PrimitiveType::String(self.chain_id.clone())); + if let Some(revision) = &self.revision { object.insert("revision".to_string(), PrimitiveType::String(revision.clone())); } - // we dont need to pass our preset types here. domain should never use a preset type PrimitiveType::Object(object).encode( "StarknetDomain", types, @@ -451,7 +446,7 @@ macro_rules! from_str { } else { <$type>::from_str($string) } - .map_err(|e| Error::InvalidMessageError(format!("Failed to parse number: {}", e))) + .map_err(|e| Error::ParseError(format!("Failed to parse number: {}", e))) }; } @@ -462,7 +457,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error for (key, value) in object { let member = struct_.children.iter_mut().find(|member| member.name == *key).ok_or_else( - || Error::InvalidMessageError(format!("Member {} not found", key)), + || Error::FieldNotFound(format!("Member {} not found", key)), )?; parse_value_to_ty(value, &mut member.ty)?; @@ -492,7 +487,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error // and the value is the variant value Ty::Enum(enum_) => { let (option_name, value) = object.first().ok_or_else(|| { - Error::InvalidMessageError("Enum variant not found".to_string()) + Error::InvalidEnum("Enum variant not found".to_string()) })?; enum_.options.iter_mut().for_each(|option| { @@ -502,11 +497,11 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error }); enum_.set_option(option_name).map_err(|e| { - Error::InvalidMessageError(format!("Failed to set enum option: {}", e)) + Error::InvalidEnum(format!("Failed to set enum option: {}", e)) })?; } _ => { - return Err(Error::InvalidMessageError(format!( + return Err(Error::InvalidType(format!( "Invalid object type for {}", ty.name() ))); @@ -529,7 +524,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error Ty::Tuple(tuple) => { // our array values need to match the length of the tuple if tuple.len() != values.len() { - return Err(Error::InvalidMessageError("Tuple length mismatch".to_string())); + return Err(Error::InvalidValue("Tuple length mismatch".to_string())); } for (i, value) in tuple.iter_mut().enumerate() { @@ -537,7 +532,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error } } _ => { - return Err(Error::InvalidMessageError(format!( + return Err(Error::InvalidType(format!( "Invalid array type for {}", ty.name() ))); @@ -573,14 +568,14 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error *usize = Some(number.as_u64().unwrap() as u32); } _ => { - return Err(Error::InvalidMessageError(format!( + return Err(Error::InvalidType(format!( "Invalid number type for {}", ty.name() ))); } }, _ => { - return Err(Error::InvalidMessageError(format!( + return Err(Error::InvalidType(format!( "Invalid number type for {}", ty.name() ))); @@ -637,14 +632,14 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error *v = Some(bool::from_str(string).unwrap()); } _ => { - return Err(Error::InvalidMessageError("Invalid primitive type".to_string())); + return Err(Error::InvalidType("Invalid primitive type".to_string())); } }, Ty::ByteArray(s) => { s.clone_from(string); } _ => { - return Err(Error::InvalidMessageError(format!( + return Err(Error::InvalidType(format!( "Invalid string type for {}", ty.name() ))); @@ -668,11 +663,11 @@ pub fn map_ty_to_primitive(ty: &Ty) -> Result { let mut object = IndexMap::new(); let option = enum_ .option - .ok_or(Error::InvalidMessageError("Enum option not found".to_string()))?; + .ok_or(Error::InvalidEnum("Enum option not found".to_string()))?; let option = enum_ .options .get(option as usize) - .ok_or(Error::InvalidMessageError("Enum option not found".to_string()))?; + .ok_or(Error::InvalidEnum("Enum option not found".to_string()))?; object.insert(option.name.clone(), map_ty_to_primitive(&option.ty)?); Ok(PrimitiveType::Object(object)) } @@ -894,27 +889,20 @@ impl TypedData { pub fn encode(&self, account: Felt) -> Result { let preset_types = get_preset_types(); - if self.domain.revision.clone().unwrap_or("1".to_string()) != "1" { - return Err(Error::InvalidMessageError( - "Legacy revision 0 is not supported".to_string(), - )); - } - - let prefix_message = cairo_short_string_to_felt("StarkNet Message").unwrap(); + let prefix_message = cairo_short_string_to_felt("StarkNet Message") + .map_err(|e| Error::CryptoError(e.to_string()))?; - // encode domain separator let domain_hash = self.domain.encode(&self.types)?; - // encode message - let message_hash = PrimitiveType::Object(self.message.clone()).encode( - &self.primary_type, - &self.types, - &preset_types, - &mut Default::default(), - )?; + let message_hash = PrimitiveType::Object(self.message.clone()) + .encode( + &self.primary_type, + &self.types, + &preset_types, + &mut Default::default(), + )?; - // return full hash - Ok(poseidon_hash_many(vec![prefix_message, domain_hash, account, message_hash].as_slice())) + Ok(poseidon_hash_many(&[prefix_message, domain_hash, account, message_hash])) } } From f39be14985981e114cfdc3ea8d4fd70544526579 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 13:55:37 +0700 Subject: [PATCH 04/13] fmt --- bin/torii/Cargo.toml | 2 +- crates/torii/libp2p/Cargo.toml | 4 +- crates/torii/libp2p/src/error.rs | 1 - crates/torii/libp2p/src/server/mod.rs | 3 +- crates/torii/libp2p/src/test.rs | 1322 ++++++++++----------- crates/torii/libp2p/src/types.rs | 1 - crates/torii/typed-data/src/typed_data.rs | 82 +- 7 files changed, 688 insertions(+), 727 deletions(-) diff --git a/bin/torii/Cargo.toml b/bin/torii/Cargo.toml index daae76922e..efa4339e0a 100644 --- a/bin/torii/Cargo.toml +++ b/bin/torii/Cargo.toml @@ -39,7 +39,7 @@ torii-cli.workspace = true torii-core.workspace = true torii-graphql.workspace = true torii-grpc = { workspace = true, features = [ "server" ] } -torii-relay = { workspace = true, features = [ "server" ] } +torii-relay.workspace = true torii-server.workspace = true tower.workspace = true diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index a60070639f..6da6959582 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -7,7 +7,7 @@ version.workspace = true [features] client = [ ] -default = [ "server" ] +default = [ "client", "server" ] server = [ "dep:sqlx", "dep:torii-core" ] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -29,6 +29,8 @@ starknet-crypto.workspace = true thiserror.workspace = true torii-typed-data.workspace = true tracing.workspace = true +sqlx = { workspace = true, optional = true } +torii-core = { workspace = true, optional = true } [dev-dependencies] katana-runner.workspace = true diff --git a/crates/torii/libp2p/src/error.rs b/crates/torii/libp2p/src/error.rs index 9326c290a4..a8234c3cce 100644 --- a/crates/torii/libp2p/src/error.rs +++ b/crates/torii/libp2p/src/error.rs @@ -6,7 +6,6 @@ use libp2p::gossipsub::{PublishError, SubscriptionError}; use libp2p::noise; use starknet::providers::ProviderError; use thiserror::Error; - use torii_typed_data::error::Error as TypedDataError; #[derive(Error, Debug)] diff --git a/crates/torii/libp2p/src/server/mod.rs b/crates/torii/libp2p/src/server/mod.rs index 56d6e8df89..f041cd5295 100644 --- a/crates/torii/libp2p/src/server/mod.rs +++ b/crates/torii/libp2p/src/server/mod.rs @@ -36,9 +36,10 @@ use crate::error::Error; mod events; +use torii_typed_data::typed_data::{parse_value_to_ty, PrimitiveType, TypedData}; + use crate::server::events::ServerEvent; use crate::types::Message; -use torii_typed_data::typed_data::{parse_value_to_ty, PrimitiveType, TypedData}; pub(crate) const LOG_TARGET: &str = "torii::relay::server"; diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index c8c18671e9..ea4dfe6cab 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -1,330 +1,261 @@ - use std::error::Error; - - use crate::client::RelayClient; - use torii_typed_data::typed_data::{ - map_ty_to_primitive, parse_value_to_ty, Domain, PrimitiveType, TypedData, - }; - - #[cfg(target_arch = "wasm32")] - wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); - use crypto_bigint::U256; - use dojo_types::primitive::Primitive; - use dojo_types::schema::{Enum, EnumOption, Member, Struct, Ty}; - use katana_runner::KatanaRunner; - use serde_json::Number; - use starknet::core::types::Felt; - #[cfg(target_arch = "wasm32")] - use wasm_bindgen_test::*; - - #[test] - fn test_parse_primitive_to_ty() { - // primitives - let mut ty = Ty::Primitive(Primitive::U8(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U8(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U16(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U16(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U32(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U32(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::USize(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::USize(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U64(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U64(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U128(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U128(Some(1)))); - - // test u256 with low high - let mut ty = Ty::Primitive(Primitive::U256(None)); - let value = PrimitiveType::Object( - vec![ - ("low".to_string(), PrimitiveType::String("1".to_string())), - ("high".to_string(), PrimitiveType::String("0".to_string())), - ] - .into_iter() - .collect(), - ); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U256(Some(U256::ONE)))); - - let mut ty = Ty::Primitive(Primitive::Felt252(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::Felt252(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::ClassHash(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::ContractAddress(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::Bool(None)); - let value = PrimitiveType::Bool(true); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::Bool(Some(true)))); - - // bytearray - let mut ty = Ty::ByteArray("".to_string()); - let value = PrimitiveType::String("mimi".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::ByteArray("mimi".to_string())); - } - - #[test] - fn test_map_ty_to_primitive() { - let ty = Ty::Primitive(Primitive::U8(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U16(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U32(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::USize(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U64(Some(1))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U128(Some(1))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U256(Some(U256::ONE))); - let value = PrimitiveType::Object( - vec![ - ("low".to_string(), PrimitiveType::String("1".to_string())), - ("high".to_string(), PrimitiveType::String("0".to_string())), - ] - .into_iter() - .collect(), - ); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::Felt252(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::Bool(Some(true))); - let value = PrimitiveType::Bool(true); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::ByteArray("mimi".to_string()); - let value = PrimitiveType::String("mimi".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - } - #[test] - fn test_parse_complex_to_ty() { - let mut ty = Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(None)), - key: true, - }, - Member { name: "name".to_string(), ty: Ty::ByteArray("".to_string()), key: false }, - Member { - name: "items".to_string(), - // array of PlayerItem struct - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - ], - })]), - key: false, - }, - // a favorite_item field with enum type Option - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: None, - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - ], - }), - }, - ], - }), - key: false, - }, - ], - }); - - let value = PrimitiveType::Object( - vec![ - ("player".to_string(), PrimitiveType::String("1".to_string())), - ("name".to_string(), PrimitiveType::String("mimi".to_string())), - ( - "items".to_string(), - PrimitiveType::Array(vec![PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::String("1".to_string())), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - )]), - ), - ( - "favorite_item".to_string(), - PrimitiveType::Object( - vec![( - "Some".to_string(), - PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::String("1".to_string())), - ( - "quantity".to_string(), - PrimitiveType::Number(Number::from(1u64)), - ), - ] - .into_iter() - .collect(), - ), - )] - .into_iter() - .collect(), - ), - ), - ] - .into_iter() - .collect(), - ); - - parse_value_to_ty(&value, &mut ty).unwrap(); - - assert_eq!( - ty, - Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), - key: true, - }, - Member { - name: "name".to_string(), - ty: Ty::ByteArray("mimi".to_string()), - key: false, - }, - Member { - name: "items".to_string(), - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - })]), - key: false, - }, - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: Some(1_u8), - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - }), - }, +use std::error::Error; + +use torii_typed_data::typed_data::{ + map_ty_to_primitive, parse_value_to_ty, Domain, PrimitiveType, TypedData, +}; + +use crate::client::RelayClient; + +#[cfg(target_arch = "wasm32")] +wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); +use crypto_bigint::U256; +use dojo_types::primitive::Primitive; +use dojo_types::schema::{Enum, EnumOption, Member, Struct, Ty}; +use katana_runner::KatanaRunner; +use serde_json::Number; +use starknet::core::types::Felt; +#[cfg(target_arch = "wasm32")] +use wasm_bindgen_test::*; + +#[test] +fn test_parse_primitive_to_ty() { + // primitives + let mut ty = Ty::Primitive(Primitive::U8(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U8(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U16(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U16(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U32(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U32(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::USize(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::USize(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U64(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U64(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U128(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U128(Some(1)))); + + // test u256 with low high + let mut ty = Ty::Primitive(Primitive::U256(None)); + let value = PrimitiveType::Object( + vec![ + ("low".to_string(), PrimitiveType::String("1".to_string())), + ("high".to_string(), PrimitiveType::String("0".to_string())), + ] + .into_iter() + .collect(), + ); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U256(Some(U256::ONE)))); + + let mut ty = Ty::Primitive(Primitive::Felt252(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::Felt252(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::ClassHash(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::ContractAddress(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::Bool(None)); + let value = PrimitiveType::Bool(true); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::Bool(Some(true)))); + + // bytearray + let mut ty = Ty::ByteArray("".to_string()); + let value = PrimitiveType::String("mimi".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::ByteArray("mimi".to_string())); +} + +#[test] +fn test_map_ty_to_primitive() { + let ty = Ty::Primitive(Primitive::U8(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U16(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U32(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::USize(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U64(Some(1))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U128(Some(1))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U256(Some(U256::ONE))); + let value = PrimitiveType::Object( + vec![ + ("low".to_string(), PrimitiveType::String("1".to_string())), + ("high".to_string(), PrimitiveType::String("0".to_string())), + ] + .into_iter() + .collect(), + ); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::Felt252(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::Bool(Some(true))); + let value = PrimitiveType::Bool(true); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::ByteArray("mimi".to_string()); + let value = PrimitiveType::String("mimi".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); +} + +#[test] +fn test_parse_complex_to_ty() { + let mut ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(None)), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("".to_string()), key: false }, + Member { + name: "items".to_string(), + // array of PlayerItem struct + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + ], + })]), + key: false, + }, + // a favorite_item field with enum type Option + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: None, + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let value = PrimitiveType::Object( + vec![ + ("player".to_string(), PrimitiveType::String("1".to_string())), + ("name".to_string(), PrimitiveType::String("mimi".to_string())), + ( + "items".to_string(), + PrimitiveType::Array(vec![PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::String("1".to_string())), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + )]), + ), + ( + "favorite_item".to_string(), + PrimitiveType::Object( + vec![( + "Some".to_string(), + PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::String("1".to_string())), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), ] - }), - key: false, - }, - ], - }) - ); - } + .into_iter() + .collect(), + ), + )] + .into_iter() + .collect(), + ), + ), + ] + .into_iter() + .collect(), + ); + + parse_value_to_ty(&value, &mut ty).unwrap(); - #[test] - fn test_map_ty_to_complex() { - let ty = Ty::Struct(Struct { + assert_eq!( + ty, + Ty::Struct(Struct { name: "PlayerConfig".to_string(), children: vec![ Member { @@ -381,372 +312,421 @@ ], }), }, - ], + ] }), key: false, }, ], - }); - - let value = PrimitiveType::Object( - vec![ - ("player".to_string(), PrimitiveType::String("1".to_string())), - ("name".to_string(), PrimitiveType::String("mimi".to_string())), - ( - "items".to_string(), - PrimitiveType::Array(vec![PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - )]), - ), - ( - "favorite_item".to_string(), - PrimitiveType::Object( - vec![( - "Some".to_string(), - PrimitiveType::Object( - vec![ - ( - "item_id".to_string(), - PrimitiveType::Number(Number::from(1u64)), - ), - ( - "quantity".to_string(), - PrimitiveType::Number(Number::from(1u64)), - ), - ] - .into_iter() - .collect(), - ), - )] - .into_iter() - .collect(), - ), + }) + ); +} + +#[test] +fn test_map_ty_to_complex() { + let ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, + Member { + name: "items".to_string(), + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + })]), + key: false, + }, + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: Some(1_u8), + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let value = PrimitiveType::Object( + vec![ + ("player".to_string(), PrimitiveType::String("1".to_string())), + ("name".to_string(), PrimitiveType::String("mimi".to_string())), + ( + "items".to_string(), + PrimitiveType::Array(vec![PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + )]), + ), + ( + "favorite_item".to_string(), + PrimitiveType::Object( + vec![( + "Some".to_string(), + PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + ), + )] + .into_iter() + .collect(), ), - ] - .into_iter() - .collect(), - ); - - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - } - - #[test] - fn test_model_to_typed_data() { - let ty = Ty::Struct(Struct { - name: "PlayerConfig".to_string(), + ), + ] + .into_iter() + .collect(), + ); + + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); +} + +#[test] +fn test_model_to_typed_data() { + let ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, + Member { + name: "items".to_string(), + // array of PlayerItem struct + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + })]), + key: false, + }, + // a favorite_item field with enum type Option + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: Some(1), + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(69))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(42))), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let typed_data = + TypedData::from_model(ty, Domain::new("Test", "1", "Test", Some("1"))).unwrap(); + + let path = "mocks/model_PlayerConfig.json"; + let file = std::fs::File::open(path).unwrap(); + let reader = std::io::BufReader::new(file); + + let file_typed_data: TypedData = serde_json::from_reader(reader).unwrap(); + + assert_eq!(typed_data.encode(Felt::ZERO).unwrap(), file_typed_data.encode(Felt::ZERO).unwrap()); +} + +// This tests subscribing to a topic and receiving a message +#[cfg(not(target_arch = "wasm32"))] +#[tokio::test] +async fn test_client_messaging() -> Result<(), Box> { + use std::sync::Arc; + use std::time::Duration; + + use dojo_types::schema::{Member, Struct, Ty}; + use dojo_world::contracts::abigen::model::Layout; + use indexmap::IndexMap; + use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; + use starknet::providers::jsonrpc::HttpTransport; + use starknet::providers::JsonRpcClient; + use starknet::signers::SigningKey; + use starknet_crypto::Felt; + use tempfile::NamedTempFile; + use tokio::select; + use tokio::sync::broadcast; + use tokio::time::sleep; + use torii_core::executor::Executor; + use torii_core::sql::cache::ModelCache; + use torii_core::sql::Sql; + use torii_core::types::{Contract, ContractType}; + use torii_typed_data::typed_data::{Domain, Field, SimpleField, TypedData}; + + use crate::server::Relay; + use crate::types::Message; + + let _ = tracing_subscriber::fmt() + .with_env_filter("torii::relay::client=debug,torii::relay::server=debug") + .try_init(); + + // Database + let tempfile = NamedTempFile::new().unwrap(); + let path = tempfile.path().to_string_lossy(); + let options = ::from_str(&path) + .unwrap() + .create_if_missing(true); + let pool = SqlitePoolOptions::new() + .min_connections(1) + .idle_timeout(None) + .max_lifetime(None) + .connect_with(options) + .await + .unwrap(); + sqlx::migrate!("../migrations").run(&pool).await.unwrap(); + + let sequencer = KatanaRunner::new().expect("Failed to create Katana sequencer"); + + let provider = Arc::new(JsonRpcClient::new(HttpTransport::new(sequencer.url()))); + + let account = sequencer.account_data(0); + + let (shutdown_tx, _) = broadcast::channel(1); + let (mut executor, sender) = + Executor::new(pool.clone(), shutdown_tx.clone(), Arc::clone(&provider), 100).await.unwrap(); + tokio::spawn(async move { + executor.run().await.unwrap(); + }); + + let model_cache = Arc::new(ModelCache::new(pool.clone())); + let mut db = Sql::new( + pool.clone(), + sender, + &[Contract { address: Felt::ZERO, r#type: ContractType::WORLD }], + model_cache, + ) + .await + .unwrap(); + + // Register the model of our Message + db.register_model( + "types_test", + &Ty::Struct(Struct { + name: "Message".to_string(), children: vec![ Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + name: "identity".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(None)), key: true, }, Member { - name: "name".to_string(), - ty: Ty::ByteArray("mimi".to_string()), - key: false, - }, - Member { - name: "items".to_string(), - // array of PlayerItem struct - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - })]), - key: false, - }, - // a favorite_item field with enum type Option - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: Some(1), - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(69))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(42))), - key: false, - }, - ], - }), - }, - ], - }), + name: "message".to_string(), + ty: Ty::ByteArray("".to_string()), key: false, }, ], - }); - - let typed_data = - TypedData::from_model(ty, Domain::new("Test", "1", "Test", Some("1"))).unwrap(); - - let path = "mocks/model_PlayerConfig.json"; - let file = std::fs::File::open(path).unwrap(); - let reader = std::io::BufReader::new(file); - - let file_typed_data: TypedData = serde_json::from_reader(reader).unwrap(); - - assert_eq!( - typed_data.encode(Felt::ZERO).unwrap(), - file_typed_data.encode(Felt::ZERO).unwrap() - ); - } - - // This tests subscribing to a topic and receiving a message - #[cfg(not(target_arch = "wasm32"))] - #[tokio::test] - async fn test_client_messaging() -> Result<(), Box> { - use std::sync::Arc; - use std::time::Duration; - - use dojo_types::schema::{Member, Struct, Ty}; - use dojo_world::contracts::abigen::model::Layout; - use indexmap::IndexMap; - use sqlx::sqlite::{SqliteConnectOptions, SqlitePoolOptions}; - use starknet::providers::jsonrpc::HttpTransport; - use starknet::providers::JsonRpcClient; - use starknet::signers::SigningKey; - use starknet_crypto::Felt; - use tempfile::NamedTempFile; - use tokio::select; - use tokio::sync::broadcast; - use tokio::time::sleep; - use torii_core::executor::Executor; - use torii_core::sql::cache::ModelCache; - use torii_core::sql::Sql; - use torii_core::types::{Contract, ContractType}; - - use crate::server::Relay; - use torii_typed_data::typed_data::{Domain, Field, SimpleField, TypedData}; - use crate::types::Message; - - let _ = tracing_subscriber::fmt() - .with_env_filter("torii::relay::client=debug,torii::relay::server=debug") - .try_init(); - - // Database - let tempfile = NamedTempFile::new().unwrap(); - let path = tempfile.path().to_string_lossy(); - let options = ::from_str(&path) - .unwrap() - .create_if_missing(true); - let pool = SqlitePoolOptions::new() - .min_connections(1) - .idle_timeout(None) - .max_lifetime(None) - .connect_with(options) - .await - .unwrap(); - sqlx::migrate!("../migrations").run(&pool).await.unwrap(); - - let sequencer = KatanaRunner::new().expect("Failed to create Katana sequencer"); - - let provider = Arc::new(JsonRpcClient::new(HttpTransport::new(sequencer.url()))); - - let account = sequencer.account_data(0); - - let (shutdown_tx, _) = broadcast::channel(1); - let (mut executor, sender) = - Executor::new(pool.clone(), shutdown_tx.clone(), Arc::clone(&provider), 100) - .await - .unwrap(); - tokio::spawn(async move { - executor.run().await.unwrap(); - }); - - let model_cache = Arc::new(ModelCache::new(pool.clone())); - let mut db = Sql::new( - pool.clone(), - sender, - &[Contract { address: Felt::ZERO, r#type: ContractType::WORLD }], - model_cache, - ) - .await - .unwrap(); - - // Register the model of our Message - db.register_model( - "types_test", - &Ty::Struct(Struct { - name: "Message".to_string(), - children: vec![ - Member { + }), + Layout::Fixed(vec![]), + Felt::ZERO, + Felt::ZERO, + 0, + 0, + 0, + None, + ) + .await + .unwrap(); + db.execute().await.unwrap(); + + // Initialize the relay server + let mut relay_server = Relay::new(db, provider, 9900, 9901, 9902, None, None)?; + tokio::spawn(async move { + relay_server.run().await; + }); + + // Initialize the first client (listener) + let client = RelayClient::new("/ip4/127.0.0.1/tcp/9900".to_string())?; + tokio::spawn(async move { + client.event_loop.lock().await.run().await; + }); + + let mut typed_data = TypedData::new( + IndexMap::from_iter(vec![ + ( + "types_test-Message".to_string(), + vec![ + Field::SimpleType(SimpleField { name: "identity".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(None)), - key: true, - }, - Member { + r#type: "ContractAddress".to_string(), + }), + Field::SimpleType(SimpleField { name: "message".to_string(), - ty: Ty::ByteArray("".to_string()), - key: false, - }, + r#type: "string".to_string(), + }), ], - }), - Layout::Fixed(vec![]), - Felt::ZERO, - Felt::ZERO, - 0, - 0, - 0, - None, - ) - .await - .unwrap(); - db.execute().await.unwrap(); - - // Initialize the relay server - let mut relay_server = Relay::new(db, provider, 9900, 9901, 9902, None, None)?; - tokio::spawn(async move { - relay_server.run().await; - }); - - // Initialize the first client (listener) - let client = RelayClient::new("/ip4/127.0.0.1/tcp/9900".to_string())?; - tokio::spawn(async move { - client.event_loop.lock().await.run().await; - }); - - let mut typed_data = TypedData::new( - IndexMap::from_iter(vec![ - ( - "types_test-Message".to_string(), - vec![ - Field::SimpleType(SimpleField { - name: "identity".to_string(), - r#type: "ContractAddress".to_string(), - }), - Field::SimpleType(SimpleField { - name: "message".to_string(), - r#type: "string".to_string(), - }), - ], - ), - ( - "StarknetDomain".to_string(), - vec![ - Field::SimpleType(SimpleField { - name: "name".to_string(), - r#type: "shortstring".to_string(), - }), - Field::SimpleType(SimpleField { - name: "version".to_string(), - r#type: "shortstring".to_string(), - }), - Field::SimpleType(SimpleField { - name: "chainId".to_string(), - r#type: "shortstring".to_string(), - }), - Field::SimpleType(SimpleField { - name: "revision".to_string(), - r#type: "shortstring".to_string(), - }), - ], - ), - ]), - "types_test-Message", - Domain::new("types_test-Message", "1", "0x0", Some("1")), - IndexMap::new(), - ); - typed_data.message.insert( - "identity".to_string(), - torii_typed_data::typed_data::PrimitiveType::String(account.address.to_string()), - ); - - typed_data.message.insert( - "message".to_string(), - torii_typed_data::typed_data::PrimitiveType::String("mimi".to_string()), - ); - - let message_hash = typed_data.encode(account.address).unwrap(); - let signature = - SigningKey::from_secret_scalar(account.private_key.clone().unwrap().secret_scalar()) - .sign(&message_hash) - .unwrap(); - - client - .command_sender - .publish(Message { message: typed_data, signature: vec![signature.r, signature.s] }) - .await?; - - sleep(std::time::Duration::from_secs(2)).await; - - loop { - select! { - entity = sqlx::query("SELECT * FROM entities").fetch_one(&pool) => if entity.is_ok() { - println!("Test OK: Received message within 5 seconds."); - return Ok(()); - }, - _ = sleep(Duration::from_secs(5)) => { - println!("Test Failed: Did not receive message within 5 seconds."); - return Err("Timeout reached without receiving a message".into()); - } - } - } - } + ), + ( + "StarknetDomain".to_string(), + vec![ + Field::SimpleType(SimpleField { + name: "name".to_string(), + r#type: "shortstring".to_string(), + }), + Field::SimpleType(SimpleField { + name: "version".to_string(), + r#type: "shortstring".to_string(), + }), + Field::SimpleType(SimpleField { + name: "chainId".to_string(), + r#type: "shortstring".to_string(), + }), + Field::SimpleType(SimpleField { + name: "revision".to_string(), + r#type: "shortstring".to_string(), + }), + ], + ), + ]), + "types_test-Message", + Domain::new("types_test-Message", "1", "0x0", Some("1")), + IndexMap::new(), + ); + typed_data.message.insert( + "identity".to_string(), + torii_typed_data::typed_data::PrimitiveType::String(account.address.to_string()), + ); + + typed_data.message.insert( + "message".to_string(), + torii_typed_data::typed_data::PrimitiveType::String("mimi".to_string()), + ); + + let message_hash = typed_data.encode(account.address).unwrap(); + let signature = + SigningKey::from_secret_scalar(account.private_key.clone().unwrap().secret_scalar()) + .sign(&message_hash) + .unwrap(); + + client + .command_sender + .publish(Message { message: typed_data, signature: vec![signature.r, signature.s] }) + .await?; - #[cfg(target_arch = "wasm32")] - #[wasm_bindgen_test] - async fn test_client_connection_wasm() -> Result<(), Box> { - use futures::future::{select, Either}; - use wasm_bindgen_futures::spawn_local; - - tracing_wasm::set_as_global_default(); - - let _ = tracing_subscriber::fmt().with_env_filter("torii_libp2p=debug").try_init(); - // Initialize the first client (listener) - // Make sure the cert hash is correct - corresponding to the cert in the relay server - let mut client = RelayClient::new( - "/ip4/127.0.0.1/udp/9091/webrtc-direct/certhash/\ - uEiCAoeHQh49fCHDolECesXO0CPR7fpz0sv0PWVaIahzT4g" - .to_string(), - )?; - - spawn_local(async move { - client.event_loop.lock().await.run().await; - }); - - client.command_sender.subscribe("mawmaw".to_string()).await?; - client.command_sender.wait_for_relay().await?; - client.command_sender.publish("mawmaw".to_string(), "mimi".as_bytes().to_vec()).await?; - - let timeout = wasm_timer::Delay::new(std::time::Duration::from_secs(2)); - let mut message_future = client.message_receiver.lock().await; - let message_future = message_future.next(); - - match select(message_future, timeout).await { - Either::Left((Some(_message), _)) => { + sleep(std::time::Duration::from_secs(2)).await; + + loop { + select! { + entity = sqlx::query("SELECT * FROM entities").fetch_one(&pool) => if entity.is_ok() { println!("Test OK: Received message within 5 seconds."); - Ok(()) - } - _ => { + return Ok(()); + }, + _ = sleep(Duration::from_secs(5)) => { println!("Test Failed: Did not receive message within 5 seconds."); - Err("Timeout reached without receiving a message".into()) + return Err("Timeout reached without receiving a message".into()); } } } +} + +#[cfg(target_arch = "wasm32")] +#[wasm_bindgen_test] +async fn test_client_connection_wasm() -> Result<(), Box> { + use futures::future::{select, Either}; + use wasm_bindgen_futures::spawn_local; + + tracing_wasm::set_as_global_default(); + + let _ = tracing_subscriber::fmt().with_env_filter("torii_libp2p=debug").try_init(); + // Initialize the first client (listener) + // Make sure the cert hash is correct - corresponding to the cert in the relay server + let mut client = RelayClient::new( + "/ip4/127.0.0.1/udp/9091/webrtc-direct/certhash/\ + uEiCAoeHQh49fCHDolECesXO0CPR7fpz0sv0PWVaIahzT4g" + .to_string(), + )?; + + spawn_local(async move { + client.event_loop.lock().await.run().await; + }); + + client.command_sender.subscribe("mawmaw".to_string()).await?; + client.command_sender.wait_for_relay().await?; + client.command_sender.publish("mawmaw".to_string(), "mimi".as_bytes().to_vec()).await?; + + let timeout = wasm_timer::Delay::new(std::time::Duration::from_secs(2)); + let mut message_future = client.message_receiver.lock().await; + let message_future = message_future.next(); + + match select(message_future, timeout).await { + Either::Left((Some(_message), _)) => { + println!("Test OK: Received message within 5 seconds."); + Ok(()) + } + _ => { + println!("Test Failed: Did not receive message within 5 seconds."); + Err("Timeout reached without receiving a message".into()) + } + } +} diff --git a/crates/torii/libp2p/src/types.rs b/crates/torii/libp2p/src/types.rs index ff6ae7ecef..e8d52c2402 100644 --- a/crates/torii/libp2p/src/types.rs +++ b/crates/torii/libp2p/src/types.rs @@ -1,6 +1,5 @@ use serde::{Deserialize, Serialize}; use starknet::core::types::Felt; - use torii_typed_data::TypedData; #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/crates/torii/typed-data/src/typed_data.rs b/crates/torii/typed-data/src/typed_data.rs index a28308ad45..ab8feb97ec 100644 --- a/crates/torii/typed-data/src/typed_data.rs +++ b/crates/torii/typed-data/src/typed_data.rs @@ -234,11 +234,10 @@ pub(crate) fn get_value_type( } fn get_hex(value: &str) -> Result { - Felt::from_str(value) - .or_else(|_| { - cairo_short_string_to_felt(value) - .map_err(|e| Error::ParseError(format!("Invalid shortstring for felt: {}", e))) - }) + Felt::from_str(value).or_else(|_| { + cairo_short_string_to_felt(value) + .map_err(|e| Error::ParseError(format!("Invalid shortstring for felt: {}", e))) + }) } impl PrimitiveType { @@ -256,9 +255,10 @@ impl PrimitiveType { let mut hashes = Vec::new(); if ctx.base_type == "enum" { - let (variant_name, value) = obj.first() - .ok_or_else(|| Error::InvalidEnum("Enum value must be populated".to_string()))?; - + let (variant_name, value) = obj.first().ok_or_else(|| { + Error::InvalidEnum("Enum value must be populated".to_string()) + })?; + let variant_type = get_value_type(variant_name, types)?; // variant index @@ -298,10 +298,7 @@ impl PrimitiveType { let type_hash = encode_type(r#type, if ctx.is_preset { preset_types } else { types })?; hashes.push(get_selector_from_name(&type_hash).map_err(|e| { - Error::ParseError(format!( - "Invalid type {} for selector: {}", - r#type, e - )) + Error::ParseError(format!("Invalid type {} for selector: {}", r#type, e)) })?); for (field_name, value) in obj { @@ -386,9 +383,8 @@ impl PrimitiveType { _ => Err(Error::InvalidType(format!("Invalid type {} for string", r#type))), }, PrimitiveType::Number(number) => { - let felt = Felt::from_str(&number.to_string()).map_err(|_| { - Error::ParseError(format!("Invalid number {}", number)) - })?; + let felt = Felt::from_str(&number.to_string()) + .map_err(|_| Error::ParseError(format!("Invalid number {}", number)))?; Ok(felt) } } @@ -416,16 +412,14 @@ impl Domain { pub fn encode(&self, types: &IndexMap>) -> Result { if self.revision.as_deref().unwrap_or("1") != "1" { - return Err(Error::InvalidDomain( - "Legacy revision 0 is not supported".to_string() - )); + return Err(Error::InvalidDomain("Legacy revision 0 is not supported".to_string())); } let mut object = IndexMap::new(); object.insert("name".to_string(), PrimitiveType::String(self.name.clone())); object.insert("version".to_string(), PrimitiveType::String(self.version.clone())); object.insert("chainId".to_string(), PrimitiveType::String(self.chain_id.clone())); - + if let Some(revision) = &self.revision { object.insert("revision".to_string(), PrimitiveType::String(revision.clone())); } @@ -486,9 +480,9 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error // where the K is the variant name // and the value is the variant value Ty::Enum(enum_) => { - let (option_name, value) = object.first().ok_or_else(|| { - Error::InvalidEnum("Enum variant not found".to_string()) - })?; + let (option_name, value) = object + .first() + .ok_or_else(|| Error::InvalidEnum("Enum variant not found".to_string()))?; enum_.options.iter_mut().for_each(|option| { if option.name == *option_name { @@ -496,15 +490,12 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error } }); - enum_.set_option(option_name).map_err(|e| { - Error::InvalidEnum(format!("Failed to set enum option: {}", e)) - })?; + enum_ + .set_option(option_name) + .map_err(|e| Error::InvalidEnum(format!("Failed to set enum option: {}", e)))?; } _ => { - return Err(Error::InvalidType(format!( - "Invalid object type for {}", - ty.name() - ))); + return Err(Error::InvalidType(format!("Invalid object type for {}", ty.name()))); } }, PrimitiveType::Array(values) => match ty { @@ -532,10 +523,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error } } _ => { - return Err(Error::InvalidType(format!( - "Invalid array type for {}", - ty.name() - ))); + return Err(Error::InvalidType(format!("Invalid array type for {}", ty.name()))); } }, PrimitiveType::Number(number) => match ty { @@ -575,10 +563,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error } }, _ => { - return Err(Error::InvalidType(format!( - "Invalid number type for {}", - ty.name() - ))); + return Err(Error::InvalidType(format!("Invalid number type for {}", ty.name()))); } }, PrimitiveType::Bool(boolean) => { @@ -639,10 +624,7 @@ pub fn parse_value_to_ty(value: &PrimitiveType, ty: &mut Ty) -> Result<(), Error s.clone_from(string); } _ => { - return Err(Error::InvalidType(format!( - "Invalid string type for {}", - ty.name() - ))); + return Err(Error::InvalidType(format!("Invalid string type for {}", ty.name()))); } }, } @@ -661,9 +643,8 @@ pub fn map_ty_to_primitive(ty: &Ty) -> Result { } Ty::Enum(enum_) => { let mut object = IndexMap::new(); - let option = enum_ - .option - .ok_or(Error::InvalidEnum("Enum option not found".to_string()))?; + let option = + enum_.option.ok_or(Error::InvalidEnum("Enum option not found".to_string()))?; let option = enum_ .options .get(option as usize) @@ -894,13 +875,12 @@ impl TypedData { let domain_hash = self.domain.encode(&self.types)?; - let message_hash = PrimitiveType::Object(self.message.clone()) - .encode( - &self.primary_type, - &self.types, - &preset_types, - &mut Default::default(), - )?; + let message_hash = PrimitiveType::Object(self.message.clone()).encode( + &self.primary_type, + &self.types, + &preset_types, + &mut Default::default(), + )?; Ok(poseidon_hash_many(&[prefix_message, domain_hash, account, message_hash])) } From 15c5a68fa522932c7f4699bedd9a96c3513ef3ec Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 14:02:23 +0700 Subject: [PATCH 05/13] lint --- Cargo.lock | 9 +++------ crates/torii/libp2p/Cargo.toml | 2 -- crates/torii/typed-data/Cargo.toml | 7 ++----- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 06b9191a7f..2e543f7da0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15871,11 +15871,9 @@ version = "1.0.9" dependencies = [ "anyhow", "chrono", - "crypto-bigint", "dojo-types 1.0.9", "dojo-world", "futures", - "indexmap 2.5.0", "katana-runner", "libp2p", "libp2p-webrtc", @@ -15884,11 +15882,13 @@ dependencies = [ "rand 0.8.5", "serde", "serde_json", + "sqlx", "starknet 0.12.0", "starknet-crypto 0.7.2", "tempfile", "thiserror 1.0.63", "tokio", + "torii-core", "torii-typed-data", "tracing", "tracing-subscriber", @@ -15936,18 +15936,15 @@ dependencies = [ name = "torii-typed-data" version = "1.0.9" dependencies = [ - "anyhow", - "chrono", + "cainome 0.4.11", "crypto-bigint", "dojo-types 1.0.9", - "dojo-world", "indexmap 2.5.0", "serde", "serde_json", "starknet 0.12.0", "starknet-crypto 0.7.2", "thiserror 1.0.63", - "tracing", ] [[package]] diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index 6da6959582..0116563929 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -19,10 +19,8 @@ serde.workspace = true # preserve order anyhow.workspace = true chrono.workspace = true -crypto-bigint.workspace = true dojo-types.workspace = true dojo-world.workspace = true -indexmap.workspace = true serde_json.workspace = true starknet.workspace = true starknet-crypto.workspace = true diff --git a/crates/torii/typed-data/Cargo.toml b/crates/torii/typed-data/Cargo.toml index 2d5e621f98..590e12d39d 100644 --- a/crates/torii/typed-data/Cargo.toml +++ b/crates/torii/typed-data/Cargo.toml @@ -10,14 +10,11 @@ version.workspace = true [dependencies] serde.workspace = true # preserve order -anyhow.workspace = true -chrono.workspace = true +cainome.workspace = true crypto-bigint.workspace = true dojo-types.workspace = true -dojo-world.workspace = true indexmap.workspace = true serde_json.workspace = true starknet-crypto.workspace = true starknet.workspace = true -thiserror.workspace = true -tracing.workspace = true \ No newline at end of file +thiserror.workspace = true \ No newline at end of file From 5de070eae5897f3becb9ee8152596541bcc55aca Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 14:27:19 +0700 Subject: [PATCH 06/13] fmt --- crates/torii/libp2p/src/test.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index ea4dfe6cab..90a052ec93 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -1,4 +1,3 @@ - use std::error::Error; use torii_typed_data::typed_data::{ From b52c0dd48128da1069718970fc7febf2d6a78b51 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 14:51:28 +0700 Subject: [PATCH 07/13] fix tests --- Cargo.lock | 1 + crates/torii/libp2p/Cargo.toml | 1 + crates/torii/libp2p/src/test.rs | 489 ---------------------------- crates/torii/typed-data/src/lib.rs | 5 +- crates/torii/typed-data/src/test.rs | 488 +++++++++++++++++++++++++++ 5 files changed, 494 insertions(+), 490 deletions(-) create mode 100644 crates/torii/typed-data/src/test.rs diff --git a/Cargo.lock b/Cargo.lock index 2e543f7da0..cb6f8206a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15874,6 +15874,7 @@ dependencies = [ "dojo-types 1.0.9", "dojo-world", "futures", + "indexmap 2.5.0", "katana-runner", "libp2p", "libp2p-webrtc", diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index 0116563929..a85b4e3ad2 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -35,6 +35,7 @@ katana-runner.workspace = true tempfile.workspace = true tokio.workspace = true tracing-subscriber.workspace = true +indexmap.workspace = true [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libp2p = { git = "https://github.com/libp2p/rust-libp2p", features = [ "dns", "ed25519", "gossipsub", "identify", "macros", "noise", "ping", "quic", "relay", "tcp", "tokio", "websocket", "yamux" ], rev = "cdc9638" } diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index 90a052ec93..21e89a5132 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -1,504 +1,15 @@ use std::error::Error; -use torii_typed_data::typed_data::{ - map_ty_to_primitive, parse_value_to_ty, Domain, PrimitiveType, TypedData, -}; use crate::client::RelayClient; #[cfg(target_arch = "wasm32")] wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); -use crypto_bigint::U256; use dojo_types::primitive::Primitive; -use dojo_types::schema::{Enum, EnumOption, Member, Struct, Ty}; use katana_runner::KatanaRunner; -use serde_json::Number; -use starknet::core::types::Felt; #[cfg(target_arch = "wasm32")] use wasm_bindgen_test::*; -#[test] -fn test_parse_primitive_to_ty() { - // primitives - let mut ty = Ty::Primitive(Primitive::U8(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U8(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U16(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U16(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U32(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U32(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::USize(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::USize(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U64(None)); - let value = PrimitiveType::Number(Number::from(1u64)); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U64(Some(1)))); - - let mut ty = Ty::Primitive(Primitive::U128(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U128(Some(1)))); - - // test u256 with low high - let mut ty = Ty::Primitive(Primitive::U256(None)); - let value = PrimitiveType::Object( - vec![ - ("low".to_string(), PrimitiveType::String("1".to_string())), - ("high".to_string(), PrimitiveType::String("0".to_string())), - ] - .into_iter() - .collect(), - ); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::U256(Some(U256::ONE)))); - - let mut ty = Ty::Primitive(Primitive::Felt252(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::Felt252(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::ClassHash(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::ContractAddress(None)); - let value = PrimitiveType::String("1".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE)))); - - let mut ty = Ty::Primitive(Primitive::Bool(None)); - let value = PrimitiveType::Bool(true); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::Primitive(Primitive::Bool(Some(true)))); - - // bytearray - let mut ty = Ty::ByteArray("".to_string()); - let value = PrimitiveType::String("mimi".to_string()); - parse_value_to_ty(&value, &mut ty).unwrap(); - assert_eq!(ty, Ty::ByteArray("mimi".to_string())); -} - -#[test] -fn test_map_ty_to_primitive() { - let ty = Ty::Primitive(Primitive::U8(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U16(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U32(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::USize(Some(1))); - let value = PrimitiveType::Number(Number::from(1u64)); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U64(Some(1))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U128(Some(1))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::U256(Some(U256::ONE))); - let value = PrimitiveType::Object( - vec![ - ("low".to_string(), PrimitiveType::String("1".to_string())), - ("high".to_string(), PrimitiveType::String("0".to_string())), - ] - .into_iter() - .collect(), - ); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::Felt252(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))); - let value = PrimitiveType::String("1".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::Primitive(Primitive::Bool(Some(true))); - let value = PrimitiveType::Bool(true); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); - - let ty = Ty::ByteArray("mimi".to_string()); - let value = PrimitiveType::String("mimi".to_string()); - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); -} - -#[test] -fn test_parse_complex_to_ty() { - let mut ty = Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(None)), - key: true, - }, - Member { name: "name".to_string(), ty: Ty::ByteArray("".to_string()), key: false }, - Member { - name: "items".to_string(), - // array of PlayerItem struct - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - ], - })]), - key: false, - }, - // a favorite_item field with enum type Option - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: None, - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(None)), - key: false, - }, - ], - }), - }, - ], - }), - key: false, - }, - ], - }); - - let value = PrimitiveType::Object( - vec![ - ("player".to_string(), PrimitiveType::String("1".to_string())), - ("name".to_string(), PrimitiveType::String("mimi".to_string())), - ( - "items".to_string(), - PrimitiveType::Array(vec![PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::String("1".to_string())), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - )]), - ), - ( - "favorite_item".to_string(), - PrimitiveType::Object( - vec![( - "Some".to_string(), - PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::String("1".to_string())), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - ), - )] - .into_iter() - .collect(), - ), - ), - ] - .into_iter() - .collect(), - ); - - parse_value_to_ty(&value, &mut ty).unwrap(); - - assert_eq!( - ty, - Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), - key: true, - }, - Member { - name: "name".to_string(), - ty: Ty::ByteArray("mimi".to_string()), - key: false, - }, - Member { - name: "items".to_string(), - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - })]), - key: false, - }, - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: Some(1_u8), - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - }), - }, - ] - }), - key: false, - }, - ], - }) - ); -} - -#[test] -fn test_map_ty_to_complex() { - let ty = Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), - key: true, - }, - Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, - Member { - name: "items".to_string(), - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - })]), - key: false, - }, - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: Some(1_u8), - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - }), - }, - ], - }), - key: false, - }, - ], - }); - - let value = PrimitiveType::Object( - vec![ - ("player".to_string(), PrimitiveType::String("1".to_string())), - ("name".to_string(), PrimitiveType::String("mimi".to_string())), - ( - "items".to_string(), - PrimitiveType::Array(vec![PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - )]), - ), - ( - "favorite_item".to_string(), - PrimitiveType::Object( - vec![( - "Some".to_string(), - PrimitiveType::Object( - vec![ - ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), - ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), - ] - .into_iter() - .collect(), - ), - )] - .into_iter() - .collect(), - ), - ), - ] - .into_iter() - .collect(), - ); - - assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); -} - -#[test] -fn test_model_to_typed_data() { - let ty = Ty::Struct(Struct { - name: "PlayerConfig".to_string(), - children: vec![ - Member { - name: "player".to_string(), - ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), - key: true, - }, - Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, - Member { - name: "items".to_string(), - // array of PlayerItem struct - ty: Ty::Array(vec![Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(1))), - key: false, - }, - ], - })]), - key: false, - }, - // a favorite_item field with enum type Option - Member { - name: "favorite_item".to_string(), - ty: Ty::Enum(Enum { - name: "Option".to_string(), - option: Some(1), - options: vec![ - EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, - EnumOption { - name: "Some".to_string(), - ty: Ty::Struct(Struct { - name: "PlayerItem".to_string(), - children: vec![ - Member { - name: "item_id".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(69))), - key: false, - }, - Member { - name: "quantity".to_string(), - ty: Ty::Primitive(Primitive::U32(Some(42))), - key: false, - }, - ], - }), - }, - ], - }), - key: false, - }, - ], - }); - - let typed_data = - TypedData::from_model(ty, Domain::new("Test", "1", "Test", Some("1"))).unwrap(); - - let path = "mocks/model_PlayerConfig.json"; - let file = std::fs::File::open(path).unwrap(); - let reader = std::io::BufReader::new(file); - - let file_typed_data: TypedData = serde_json::from_reader(reader).unwrap(); - - assert_eq!(typed_data.encode(Felt::ZERO).unwrap(), file_typed_data.encode(Felt::ZERO).unwrap()); -} - // This tests subscribing to a topic and receiving a message #[cfg(not(target_arch = "wasm32"))] #[tokio::test] diff --git a/crates/torii/typed-data/src/lib.rs b/crates/torii/typed-data/src/lib.rs index 9b69d5d25a..d60ed5e4cf 100644 --- a/crates/torii/typed-data/src/lib.rs +++ b/crates/torii/typed-data/src/lib.rs @@ -1,6 +1,9 @@ #![warn(unused_crate_dependencies)] +#[cfg(test)] +mod test; + pub mod error; pub mod typed_data; -pub use typed_data::TypedData; +pub use typed_data::TypedData; \ No newline at end of file diff --git a/crates/torii/typed-data/src/test.rs b/crates/torii/typed-data/src/test.rs new file mode 100644 index 0000000000..8dcdbd7421 --- /dev/null +++ b/crates/torii/typed-data/src/test.rs @@ -0,0 +1,488 @@ +use crypto_bigint::U256; +use dojo_types::{primitive::Primitive, schema::{Enum, EnumOption, Member, Struct, Ty}}; +use serde_json::Number; +use starknet_crypto::Felt; + +use crate::typed_data::{map_ty_to_primitive, parse_value_to_ty, Domain, PrimitiveType, TypedData}; + +#[test] +fn test_parse_primitive_to_ty() { + // primitives + let mut ty = Ty::Primitive(Primitive::U8(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U8(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U16(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U16(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U32(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U32(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::USize(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::USize(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U64(None)); + let value = PrimitiveType::Number(Number::from(1u64)); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U64(Some(1)))); + + let mut ty = Ty::Primitive(Primitive::U128(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U128(Some(1)))); + + // test u256 with low high + let mut ty = Ty::Primitive(Primitive::U256(None)); + let value = PrimitiveType::Object( + vec![ + ("low".to_string(), PrimitiveType::String("1".to_string())), + ("high".to_string(), PrimitiveType::String("0".to_string())), + ] + .into_iter() + .collect(), + ); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::U256(Some(U256::ONE)))); + + let mut ty = Ty::Primitive(Primitive::Felt252(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::Felt252(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::ClassHash(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::ContractAddress(None)); + let value = PrimitiveType::String("1".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE)))); + + let mut ty = Ty::Primitive(Primitive::Bool(None)); + let value = PrimitiveType::Bool(true); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::Primitive(Primitive::Bool(Some(true)))); + + // bytearray + let mut ty = Ty::ByteArray("".to_string()); + let value = PrimitiveType::String("mimi".to_string()); + parse_value_to_ty(&value, &mut ty).unwrap(); + assert_eq!(ty, Ty::ByteArray("mimi".to_string())); +} + +#[test] +fn test_map_ty_to_primitive() { + let ty = Ty::Primitive(Primitive::U8(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U16(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U32(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::USize(Some(1))); + let value = PrimitiveType::Number(Number::from(1u64)); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U64(Some(1))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U128(Some(1))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::U256(Some(U256::ONE))); + let value = PrimitiveType::Object( + vec![ + ("low".to_string(), PrimitiveType::String("1".to_string())), + ("high".to_string(), PrimitiveType::String("0".to_string())), + ] + .into_iter() + .collect(), + ); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::Felt252(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::ClassHash(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))); + let value = PrimitiveType::String("1".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::Primitive(Primitive::Bool(Some(true))); + let value = PrimitiveType::Bool(true); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); + + let ty = Ty::ByteArray("mimi".to_string()); + let value = PrimitiveType::String("mimi".to_string()); + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); +} + +#[test] +fn test_parse_complex_to_ty() { + let mut ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(None)), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("".to_string()), key: false }, + Member { + name: "items".to_string(), + // array of PlayerItem struct + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + ], + })]), + key: false, + }, + // a favorite_item field with enum type Option + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: None, + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(None)), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let value = PrimitiveType::Object( + vec![ + ("player".to_string(), PrimitiveType::String("1".to_string())), + ("name".to_string(), PrimitiveType::String("mimi".to_string())), + ( + "items".to_string(), + PrimitiveType::Array(vec![PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::String("1".to_string())), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + )]), + ), + ( + "favorite_item".to_string(), + PrimitiveType::Object( + vec![( + "Some".to_string(), + PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::String("1".to_string())), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + ), + )] + .into_iter() + .collect(), + ), + ), + ] + .into_iter() + .collect(), + ); + + parse_value_to_ty(&value, &mut ty).unwrap(); + + assert_eq!( + ty, + Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + key: true, + }, + Member { + name: "name".to_string(), + ty: Ty::ByteArray("mimi".to_string()), + key: false, + }, + Member { + name: "items".to_string(), + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + })]), + key: false, + }, + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: Some(1_u8), + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + }), + }, + ] + }), + key: false, + }, + ], + }) + ); +} + +#[test] +fn test_map_ty_to_complex() { + let ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, + Member { + name: "items".to_string(), + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + })]), + key: false, + }, + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: Some(1_u8), + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let value = PrimitiveType::Object( + vec![ + ("player".to_string(), PrimitiveType::String("1".to_string())), + ("name".to_string(), PrimitiveType::String("mimi".to_string())), + ( + "items".to_string(), + PrimitiveType::Array(vec![PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + )]), + ), + ( + "favorite_item".to_string(), + PrimitiveType::Object( + vec![( + "Some".to_string(), + PrimitiveType::Object( + vec![ + ("item_id".to_string(), PrimitiveType::Number(Number::from(1u64))), + ("quantity".to_string(), PrimitiveType::Number(Number::from(1u64))), + ] + .into_iter() + .collect(), + ), + )] + .into_iter() + .collect(), + ), + ), + ] + .into_iter() + .collect(), + ); + + assert_eq!(value, map_ty_to_primitive(&ty).unwrap()); +} + +#[test] +fn test_model_to_typed_data() { + let ty = Ty::Struct(Struct { + name: "PlayerConfig".to_string(), + children: vec![ + Member { + name: "player".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(Some(Felt::ONE))), + key: true, + }, + Member { name: "name".to_string(), ty: Ty::ByteArray("mimi".to_string()), key: false }, + Member { + name: "items".to_string(), + // array of PlayerItem struct + ty: Ty::Array(vec![Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(1))), + key: false, + }, + ], + })]), + key: false, + }, + // a favorite_item field with enum type Option + Member { + name: "favorite_item".to_string(), + ty: Ty::Enum(Enum { + name: "Option".to_string(), + option: Some(1), + options: vec![ + EnumOption { name: "None".to_string(), ty: Ty::Tuple(vec![]) }, + EnumOption { + name: "Some".to_string(), + ty: Ty::Struct(Struct { + name: "PlayerItem".to_string(), + children: vec![ + Member { + name: "item_id".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(69))), + key: false, + }, + Member { + name: "quantity".to_string(), + ty: Ty::Primitive(Primitive::U32(Some(42))), + key: false, + }, + ], + }), + }, + ], + }), + key: false, + }, + ], + }); + + let typed_data = + TypedData::from_model(ty, Domain::new("Test", "1", "Test", Some("1"))).unwrap(); + + let path = "mocks/model_PlayerConfig.json"; + let file = std::fs::File::open(path).unwrap(); + let reader = std::io::BufReader::new(file); + + let file_typed_data: TypedData = serde_json::from_reader(reader).unwrap(); + + assert_eq!(typed_data.encode(Felt::ZERO).unwrap(), file_typed_data.encode(Felt::ZERO).unwrap()); +} \ No newline at end of file From 4bf016c8345053bcde8723cd4c564aa212ea44b8 Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 14:54:34 +0700 Subject: [PATCH 08/13] fmt --- crates/torii/libp2p/src/test.rs | 1 - crates/torii/typed-data/src/lib.rs | 2 +- crates/torii/typed-data/src/test.rs | 5 +++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index 21e89a5132..d867719493 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -1,6 +1,5 @@ use std::error::Error; - use crate::client::RelayClient; #[cfg(target_arch = "wasm32")] diff --git a/crates/torii/typed-data/src/lib.rs b/crates/torii/typed-data/src/lib.rs index d60ed5e4cf..bf289fda18 100644 --- a/crates/torii/typed-data/src/lib.rs +++ b/crates/torii/typed-data/src/lib.rs @@ -6,4 +6,4 @@ mod test; pub mod error; pub mod typed_data; -pub use typed_data::TypedData; \ No newline at end of file +pub use typed_data::TypedData; diff --git a/crates/torii/typed-data/src/test.rs b/crates/torii/typed-data/src/test.rs index 8dcdbd7421..1dc71203c3 100644 --- a/crates/torii/typed-data/src/test.rs +++ b/crates/torii/typed-data/src/test.rs @@ -1,5 +1,6 @@ use crypto_bigint::U256; -use dojo_types::{primitive::Primitive, schema::{Enum, EnumOption, Member, Struct, Ty}}; +use dojo_types::primitive::Primitive; +use dojo_types::schema::{Enum, EnumOption, Member, Struct, Ty}; use serde_json::Number; use starknet_crypto::Felt; @@ -485,4 +486,4 @@ fn test_model_to_typed_data() { let file_typed_data: TypedData = serde_json::from_reader(reader).unwrap(); assert_eq!(typed_data.encode(Felt::ZERO).unwrap(), file_typed_data.encode(Felt::ZERO).unwrap()); -} \ No newline at end of file +} From c3411b9492e23dd67851576a788d3ff2642f3bab Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 16:43:56 +0700 Subject: [PATCH 09/13] fix clippy --- Cargo.lock | 10 +++++----- bin/torii/Cargo.toml | 2 +- crates/torii/libp2p/Cargo.toml | 30 ++++++++++++++++-------------- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb6f8206a6..f474a1b202 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2001,7 +2001,7 @@ dependencies = [ "bitflags 2.6.0", "cexpr", "clang-sys", - "itertools 0.12.1", + "itertools 0.11.0", "lazy_static", "lazycell", "log", @@ -11609,8 +11609,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "22505a5c94da8e3b7c2996394d1c933236c4d743e81a410bcca4e6989fc066a4" dependencies = [ "bytes", - "heck 0.5.0", - "itertools 0.12.1", + "heck 0.4.1", + "itertools 0.11.0", "log", "multimap", "once_cell", @@ -11630,7 +11630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c1318b19085f08681016926435853bbf7858f9c082d0999b80550ff5d9abe15" dependencies = [ "bytes", - "heck 0.5.0", + "heck 0.4.1", "itertools 0.13.0", "log", "multimap", @@ -11651,7 +11651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "81bddcdb20abf9501610992b6759a4c888aef7d1a7247ef75e2404275ac24af1" dependencies = [ "anyhow", - "itertools 0.12.1", + "itertools 0.11.0", "proc-macro2", "quote", "syn 2.0.90", diff --git a/bin/torii/Cargo.toml b/bin/torii/Cargo.toml index efa4339e0a..c021c4e00b 100644 --- a/bin/torii/Cargo.toml +++ b/bin/torii/Cargo.toml @@ -39,7 +39,7 @@ torii-cli.workspace = true torii-core.workspace = true torii-graphql.workspace = true torii-grpc = { workspace = true, features = [ "server" ] } -torii-relay.workspace = true +torii-relay = { workspace = true, features = [ "client", "server" ] } torii-server.workspace = true tower.workspace = true diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index a85b4e3ad2..a3d120630b 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -7,45 +7,47 @@ version.workspace = true [features] client = [ ] -default = [ "client", "server" ] -server = [ "dep:sqlx", "dep:torii-core" ] +server = [ "dep:sqlx", "dep:torii-core", "dep:dojo-types", "dep:dojo-world", "dep:starknet-crypto", "dep:chrono", "dep:libp2p-webrtc", "dep:rand" ] # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] futures.workspace = true -rand.workspace = true serde.workspace = true # preserve order anyhow.workspace = true -chrono.workspace = true -dojo-types.workspace = true -dojo-world.workspace = true serde_json.workspace = true starknet.workspace = true -starknet-crypto.workspace = true thiserror.workspace = true torii-typed-data.workspace = true tracing.workspace = true sqlx = { workspace = true, optional = true } torii-core = { workspace = true, optional = true } +dojo-types = { workspace = true, optional = true } +dojo-world = { workspace = true, optional = true } +rand = { workspace = true, optional = true } +starknet-crypto = { workspace = true, optional = true } +chrono = { workspace = true, optional = true } +libp2p-webrtc = { git = "https://github.com/libp2p/rust-libp2p", features = [ "pem", "tokio" ], rev = "cdc9638", optional = true } [dev-dependencies] +indexmap.workspace = true katana-runner.workspace = true tempfile.workspace = true tokio.workspace = true tracing-subscriber.workspace = true -indexmap.workspace = true + +[target.'cfg(target_arch = "wasm32")'.dev-dependencies] +tracing-wasm = "0.2.1" +wasm-bindgen-futures = "0.4.40" +wasm-bindgen-test = "0.3.40" +wasm-timer = "0.2.5" + [target.'cfg(not(target_arch = "wasm32"))'.dependencies] libp2p = { git = "https://github.com/libp2p/rust-libp2p", features = [ "dns", "ed25519", "gossipsub", "identify", "macros", "noise", "ping", "quic", "relay", "tcp", "tokio", "websocket", "yamux" ], rev = "cdc9638" } -libp2p-webrtc = { git = "https://github.com/libp2p/rust-libp2p", features = [ "pem", "tokio" ], rev = "cdc9638" } [target.'cfg(target_arch = "wasm32")'.dependencies] libp2p = { git = "https://github.com/libp2p/rust-libp2p", features = [ "ed25519", "gossipsub", "identify", "macros", "noise", "ping", "tcp", "wasm-bindgen", "yamux" ], rev = "cdc9638" } libp2p-webrtc-websys = { git = "https://github.com/libp2p/rust-libp2p", rev = "cdc9638" } -libp2p-websocket-websys = { git = "https://github.com/libp2p/rust-libp2p", rev = "cdc9638" } -tracing-wasm = "0.2.1" -wasm-bindgen-futures = "0.4.40" -wasm-bindgen-test = "0.3.40" -wasm-timer = "0.2.5" +libp2p-websocket-websys = { git = "https://github.com/libp2p/rust-libp2p", rev = "cdc9638" } \ No newline at end of file From e9a8ca754f5c4409c0a39bdf7ac7be7ae86a1f2f Mon Sep 17 00:00:00 2001 From: Nasr Date: Wed, 8 Jan 2025 17:07:02 +0700 Subject: [PATCH 10/13] move mocks to td --- crates/torii/{libp2p => typed-data}/mocks/example_baseTypes.json | 0 crates/torii/{libp2p => typed-data}/mocks/example_enum.json | 0 .../torii/{libp2p => typed-data}/mocks/example_presetTypes.json | 0 crates/torii/{libp2p => typed-data}/mocks/mail_StructArray.json | 0 crates/torii/{libp2p => typed-data}/mocks/model_PlayerConfig.json | 0 5 files changed, 0 insertions(+), 0 deletions(-) rename crates/torii/{libp2p => typed-data}/mocks/example_baseTypes.json (100%) rename crates/torii/{libp2p => typed-data}/mocks/example_enum.json (100%) rename crates/torii/{libp2p => typed-data}/mocks/example_presetTypes.json (100%) rename crates/torii/{libp2p => typed-data}/mocks/mail_StructArray.json (100%) rename crates/torii/{libp2p => typed-data}/mocks/model_PlayerConfig.json (100%) diff --git a/crates/torii/libp2p/mocks/example_baseTypes.json b/crates/torii/typed-data/mocks/example_baseTypes.json similarity index 100% rename from crates/torii/libp2p/mocks/example_baseTypes.json rename to crates/torii/typed-data/mocks/example_baseTypes.json diff --git a/crates/torii/libp2p/mocks/example_enum.json b/crates/torii/typed-data/mocks/example_enum.json similarity index 100% rename from crates/torii/libp2p/mocks/example_enum.json rename to crates/torii/typed-data/mocks/example_enum.json diff --git a/crates/torii/libp2p/mocks/example_presetTypes.json b/crates/torii/typed-data/mocks/example_presetTypes.json similarity index 100% rename from crates/torii/libp2p/mocks/example_presetTypes.json rename to crates/torii/typed-data/mocks/example_presetTypes.json diff --git a/crates/torii/libp2p/mocks/mail_StructArray.json b/crates/torii/typed-data/mocks/mail_StructArray.json similarity index 100% rename from crates/torii/libp2p/mocks/mail_StructArray.json rename to crates/torii/typed-data/mocks/mail_StructArray.json diff --git a/crates/torii/libp2p/mocks/model_PlayerConfig.json b/crates/torii/typed-data/mocks/model_PlayerConfig.json similarity index 100% rename from crates/torii/libp2p/mocks/model_PlayerConfig.json rename to crates/torii/typed-data/mocks/model_PlayerConfig.json From 81a468d1d30af908d51a00e99190216bacdcc025 Mon Sep 17 00:00:00 2001 From: Nasr Date: Thu, 9 Jan 2025 11:50:12 +0700 Subject: [PATCH 11/13] fix deps --- Cargo.lock | 132 ++++++++++++++++++++++----------- crates/torii/libp2p/Cargo.toml | 2 +- 2 files changed, 89 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f474a1b202..8e29039ebf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -15683,11 +15683,12 @@ dependencies = [ "tokio-util", "toml 0.8.19", "torii-cli", - "torii-core", "torii-graphql", "torii-grpc", + "torii-indexer", "torii-relay", "torii-server", + "torii-sqlite", "tower 0.4.13", "tower-http 0.4.4", "tracing", @@ -15708,7 +15709,7 @@ dependencies = [ "serde", "starknet 0.12.0", "toml 0.8.19", - "torii-core", + "torii-sqlite", "url", ] @@ -15740,44 +15741,6 @@ dependencies = [ "url", ] -[[package]] -name = "torii-core" -version = "1.0.9" -dependencies = [ - "anyhow", - "async-trait", - "base64 0.21.7", - "bitflags 2.6.0", - "cainome 0.4.11", - "chrono", - "crypto-bigint", - "data-url", - "dojo-test-utils", - "dojo-types 1.0.9", - "dojo-utils", - "dojo-world", - "futures-channel", - "futures-util", - "hashlink", - "ipfs-api-backend-hyper", - "katana-runner", - "once_cell", - "reqwest 0.11.27", - "scarb", - "serde", - "serde_json", - "slab", - "sozo-scarbext", - "sqlx", - "starknet 0.12.0", - "starknet-crypto 0.7.2", - "tempfile", - "thiserror 1.0.63", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "torii-graphql" version = "1.0.9" @@ -15812,7 +15775,8 @@ dependencies = [ "tokio", "tokio-stream", "toml 0.8.19", - "torii-core", + "torii-indexer", + "torii-sqlite", "tracing", "url", "warp", @@ -15859,12 +15823,53 @@ dependencies = [ "tonic-reflection", "tonic-web", "tonic-web-wasm-client", - "torii-core", + "torii-indexer", + "torii-sqlite", "tower 0.4.13", "tower-http 0.4.4", "tracing", ] +[[package]] +name = "torii-indexer" +version = "1.0.9" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "bitflags 2.6.0", + "cainome 0.4.11", + "chrono", + "crypto-bigint", + "data-url", + "dojo-test-utils", + "dojo-types 1.0.9", + "dojo-utils", + "dojo-world", + "futures-channel", + "futures-util", + "hashlink", + "ipfs-api-backend-hyper", + "katana-runner", + "num-traits 0.2.19", + "once_cell", + "reqwest 0.11.27", + "scarb", + "serde", + "serde_json", + "slab", + "sozo-scarbext", + "sqlx", + "starknet 0.12.0", + "starknet-crypto 0.7.2", + "tempfile", + "thiserror 1.0.63", + "tokio", + "tokio-util", + "torii-sqlite", + "tracing", +] + [[package]] name = "torii-relay" version = "1.0.9" @@ -15889,7 +15894,7 @@ dependencies = [ "tempfile", "thiserror 1.0.63", "tokio", - "torii-core", + "torii-sqlite", "torii-typed-data", "tracing", "tracing-subscriber", @@ -15926,13 +15931,52 @@ dependencies = [ "tokio", "tokio-tungstenite 0.20.1", "tokio-util", - "torii-core", + "torii-sqlite", "tower 0.4.13", "tower-http 0.4.4", "tracing", "warp", ] +[[package]] +name = "torii-sqlite" +version = "1.0.9" +dependencies = [ + "anyhow", + "async-trait", + "base64 0.21.7", + "bitflags 2.6.0", + "cainome 0.4.11", + "chrono", + "crypto-bigint", + "data-url", + "dojo-test-utils", + "dojo-types 1.0.9", + "dojo-utils", + "dojo-world", + "futures-channel", + "futures-util", + "hashlink", + "ipfs-api-backend-hyper", + "katana-runner", + "once_cell", + "reqwest 0.11.27", + "scarb", + "serde", + "serde_json", + "slab", + "sozo-scarbext", + "sqlx", + "starknet 0.12.0", + "starknet-crypto 0.7.2", + "tempfile", + "thiserror 1.0.63", + "tokio", + "tokio-util", + "torii-indexer", + "tracing", +] + [[package]] name = "torii-typed-data" version = "1.0.9" diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index 18a257e816..6d57276b44 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -22,7 +22,7 @@ thiserror.workspace = true torii-typed-data.workspace = true tracing.workspace = true sqlx = { workspace = true, optional = true } -torii-core = { workspace = true, optional = true } +torii-sqlite = { workspace = true, optional = true } dojo-types = { workspace = true, optional = true } dojo-world = { workspace = true, optional = true } rand = { workspace = true, optional = true } From 1f1d3140481057bf19580a0b245434a1bdb40ec7 Mon Sep 17 00:00:00 2001 From: Nasr Date: Thu, 9 Jan 2025 11:53:12 +0700 Subject: [PATCH 12/13] log targets --- .../torii/indexer/src/processors/erc20_legacy_transfer.rs | 2 +- crates/torii/indexer/src/processors/erc20_transfer.rs | 2 +- .../indexer/src/processors/erc721_legacy_transfer.rs | 2 +- crates/torii/indexer/src/processors/erc721_transfer.rs | 2 +- crates/torii/indexer/src/processors/event_message.rs | 2 +- crates/torii/indexer/src/processors/metadata_update.rs | 2 +- crates/torii/indexer/src/processors/register_event.rs | 2 +- crates/torii/indexer/src/processors/register_model.rs | 2 +- crates/torii/indexer/src/processors/store_del_record.rs | 2 +- crates/torii/indexer/src/processors/store_set_record.rs | 2 +- .../torii/indexer/src/processors/store_update_member.rs | 2 +- .../torii/indexer/src/processors/store_update_record.rs | 2 +- crates/torii/indexer/src/processors/upgrade_event.rs | 2 +- crates/torii/indexer/src/processors/upgrade_model.rs | 2 +- crates/torii/libp2p/src/test.rs | 8 ++++---- crates/torii/sqlite/src/executor/mod.rs | 2 +- 16 files changed, 19 insertions(+), 19 deletions(-) diff --git a/crates/torii/indexer/src/processors/erc20_legacy_transfer.rs b/crates/torii/indexer/src/processors/erc20_legacy_transfer.rs index 102b2016bc..3b207d466b 100644 --- a/crates/torii/indexer/src/processors/erc20_legacy_transfer.rs +++ b/crates/torii/indexer/src/processors/erc20_legacy_transfer.rs @@ -9,7 +9,7 @@ use tracing::debug; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc20_legacy_transfer"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::erc20_legacy_transfer"; #[derive(Default, Debug)] pub struct Erc20LegacyTransferProcessor; diff --git a/crates/torii/indexer/src/processors/erc20_transfer.rs b/crates/torii/indexer/src/processors/erc20_transfer.rs index c7ada3eb79..a0643abd41 100644 --- a/crates/torii/indexer/src/processors/erc20_transfer.rs +++ b/crates/torii/indexer/src/processors/erc20_transfer.rs @@ -9,7 +9,7 @@ use tracing::debug; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc20_transfer"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::erc20_transfer"; #[derive(Default, Debug)] pub struct Erc20TransferProcessor; diff --git a/crates/torii/indexer/src/processors/erc721_legacy_transfer.rs b/crates/torii/indexer/src/processors/erc721_legacy_transfer.rs index 9290c7b656..df6b2a88de 100644 --- a/crates/torii/indexer/src/processors/erc721_legacy_transfer.rs +++ b/crates/torii/indexer/src/processors/erc721_legacy_transfer.rs @@ -9,7 +9,7 @@ use tracing::debug; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc721_legacy_transfer"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::erc721_legacy_transfer"; #[derive(Default, Debug)] pub struct Erc721LegacyTransferProcessor; diff --git a/crates/torii/indexer/src/processors/erc721_transfer.rs b/crates/torii/indexer/src/processors/erc721_transfer.rs index 0b5f311b43..faf124360b 100644 --- a/crates/torii/indexer/src/processors/erc721_transfer.rs +++ b/crates/torii/indexer/src/processors/erc721_transfer.rs @@ -9,7 +9,7 @@ use tracing::debug; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc721_transfer"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::erc721_transfer"; #[derive(Default, Debug)] pub struct Erc721TransferProcessor; diff --git a/crates/torii/indexer/src/processors/event_message.rs b/crates/torii/indexer/src/processors/event_message.rs index 32f5e20613..4495665bed 100644 --- a/crates/torii/indexer/src/processors/event_message.rs +++ b/crates/torii/indexer/src/processors/event_message.rs @@ -10,7 +10,7 @@ use tracing::info; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::event_message"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::event_message"; #[derive(Default, Debug)] pub struct EventMessageProcessor; diff --git a/crates/torii/indexer/src/processors/metadata_update.rs b/crates/torii/indexer/src/processors/metadata_update.rs index 29f211f441..ec2c4b493d 100644 --- a/crates/torii/indexer/src/processors/metadata_update.rs +++ b/crates/torii/indexer/src/processors/metadata_update.rs @@ -16,7 +16,7 @@ use tracing::{error, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::metadata_update"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::metadata_update"; #[derive(Default, Debug)] pub struct MetadataUpdateProcessor; diff --git a/crates/torii/indexer/src/processors/register_event.rs b/crates/torii/indexer/src/processors/register_event.rs index 11c1d10680..e9c94f296a 100644 --- a/crates/torii/indexer/src/processors/register_event.rs +++ b/crates/torii/indexer/src/processors/register_event.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::register_event"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::register_event"; #[derive(Default, Debug)] pub struct RegisterEventProcessor; diff --git a/crates/torii/indexer/src/processors/register_model.rs b/crates/torii/indexer/src/processors/register_model.rs index 60000b340b..d630feff88 100644 --- a/crates/torii/indexer/src/processors/register_model.rs +++ b/crates/torii/indexer/src/processors/register_model.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::register_model"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::register_model"; #[derive(Default, Debug)] pub struct RegisterModelProcessor; diff --git a/crates/torii/indexer/src/processors/store_del_record.rs b/crates/torii/indexer/src/processors/store_del_record.rs index f343225777..e109f069d7 100644 --- a/crates/torii/indexer/src/processors/store_del_record.rs +++ b/crates/torii/indexer/src/processors/store_del_record.rs @@ -9,7 +9,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::store_del_record"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::store_del_record"; #[derive(Default, Debug)] pub struct StoreDelRecordProcessor; diff --git a/crates/torii/indexer/src/processors/store_set_record.rs b/crates/torii/indexer/src/processors/store_set_record.rs index 06e23dc5fa..c564cb3968 100644 --- a/crates/torii/indexer/src/processors/store_set_record.rs +++ b/crates/torii/indexer/src/processors/store_set_record.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::store_set_record"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::store_set_record"; #[derive(Default, Debug)] pub struct StoreSetRecordProcessor; diff --git a/crates/torii/indexer/src/processors/store_update_member.rs b/crates/torii/indexer/src/processors/store_update_member.rs index afbff78c41..776d61d9cb 100644 --- a/crates/torii/indexer/src/processors/store_update_member.rs +++ b/crates/torii/indexer/src/processors/store_update_member.rs @@ -11,7 +11,7 @@ use tracing::info; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::store_update_member"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::store_update_member"; #[derive(Default, Debug)] pub struct StoreUpdateMemberProcessor; diff --git a/crates/torii/indexer/src/processors/store_update_record.rs b/crates/torii/indexer/src/processors/store_update_record.rs index 80b207aa2a..b92344849d 100644 --- a/crates/torii/indexer/src/processors/store_update_record.rs +++ b/crates/torii/indexer/src/processors/store_update_record.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::store_update_record"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::store_update_record"; #[derive(Default, Debug)] pub struct StoreUpdateRecordProcessor; diff --git a/crates/torii/indexer/src/processors/upgrade_event.rs b/crates/torii/indexer/src/processors/upgrade_event.rs index 5e316b964e..ba7966d63b 100644 --- a/crates/torii/indexer/src/processors/upgrade_event.rs +++ b/crates/torii/indexer/src/processors/upgrade_event.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::upgrade_event"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::upgrade_event"; #[derive(Default, Debug)] pub struct UpgradeEventProcessor; diff --git a/crates/torii/indexer/src/processors/upgrade_model.rs b/crates/torii/indexer/src/processors/upgrade_model.rs index 5f7859e5fb..40717df30d 100644 --- a/crates/torii/indexer/src/processors/upgrade_model.rs +++ b/crates/torii/indexer/src/processors/upgrade_model.rs @@ -10,7 +10,7 @@ use tracing::{debug, info}; use super::{EventProcessor, EventProcessorConfig}; -pub(crate) const LOG_TARGET: &str = "torii_core::processors::upgrade_model"; +pub(crate) const LOG_TARGET: &str = "torii_indexer::processors::upgrade_model"; #[derive(Default, Debug)] pub struct UpgradeModelProcessor; diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index d867719493..e3c08590c8 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -28,10 +28,10 @@ async fn test_client_messaging() -> Result<(), Box> { use tokio::select; use tokio::sync::broadcast; use tokio::time::sleep; - use torii_core::executor::Executor; - use torii_core::sql::cache::ModelCache; - use torii_core::sql::Sql; - use torii_core::types::{Contract, ContractType}; + use torii_sqlite::executor::Executor; + use torii_sqlite::cache::ModelCache; + use torii_sqlite::Sql; + use torii_sqlite::types::{Contract, ContractType}; use torii_typed_data::typed_data::{Domain, Field, SimpleField, TypedData}; use crate::server::Relay; diff --git a/crates/torii/sqlite/src/executor/mod.rs b/crates/torii/sqlite/src/executor/mod.rs index 8058485107..0b0c19b6ff 100644 --- a/crates/torii/sqlite/src/executor/mod.rs +++ b/crates/torii/sqlite/src/executor/mod.rs @@ -30,7 +30,7 @@ use crate::utils::{felt_to_sql_string, I256}; pub mod erc; pub use erc::{RegisterErc20TokenQuery, RegisterErc721TokenMetadata, RegisterErc721TokenQuery}; -pub(crate) const LOG_TARGET: &str = "torii_core::executor"; +pub(crate) const LOG_TARGET: &str = "torii_sqlite::executor"; #[derive(Debug, Clone)] pub enum Argument { From 37731a9e652c3f4b441b43339b0be66810714aad Mon Sep 17 00:00:00 2001 From: Nasr Date: Thu, 9 Jan 2025 11:55:20 +0700 Subject: [PATCH 13/13] fmt --- crates/torii/libp2p/src/test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/torii/libp2p/src/test.rs b/crates/torii/libp2p/src/test.rs index e3c08590c8..35c6a85965 100644 --- a/crates/torii/libp2p/src/test.rs +++ b/crates/torii/libp2p/src/test.rs @@ -28,10 +28,10 @@ async fn test_client_messaging() -> Result<(), Box> { use tokio::select; use tokio::sync::broadcast; use tokio::time::sleep; - use torii_sqlite::executor::Executor; use torii_sqlite::cache::ModelCache; - use torii_sqlite::Sql; + use torii_sqlite::executor::Executor; use torii_sqlite::types::{Contract, ContractType}; + use torii_sqlite::Sql; use torii_typed_data::typed_data::{Domain, Field, SimpleField, TypedData}; use crate::server::Relay;