From bc35dd0b1a7ea0ccb0bdb17583ef89c6c6b90d58 Mon Sep 17 00:00:00 2001 From: glihm Date: Tue, 11 Jun 2024 21:55:51 -0600 Subject: [PATCH 01/32] [dev] add foundry tools to the dev container (#2045) * feat: add foundry install * fix: attempt a new path for bashrc * fix: use dot as we're in shell instead of source --- .devcontainer/Dockerfile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 8c8d028a18..ed7155c5c1 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -17,6 +17,8 @@ RUN curl -s https://apt.llvm.org/llvm-snapshot.gpg.key | tee /etc/apt/trusted.gp RUN echo "deb http://apt.llvm.org/${VARIANT}/ llvm-toolchain-${VARIANT}-17 main" | tee /etc/apt/sources.list.d/llvm.list && apt-get update RUN apt-get -y install -t llvm-toolchain-${VARIANT}-17 llvm-17 llvm-17-dev llvm-17-runtime clang-17 clang-tools-17 lld-17 libpolly-17-dev libmlir-17-dev mlir-17-tools +RUN curl -L https://foundry.paradigm.xyz/ | bash && . /root/.bashrc && foundryup + # To build Katana with 'native' feature, we need to set the following environment variables ENV MLIR_SYS_170_PREFIX=/usr/lib/llvm-17 ENV LLVM_SYS_170_PREFIX=/usr/lib/llvm-17 From b91c7f3a4176cef5355c97c1f3f4de06ef9d6629 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Wed, 12 Jun 2024 10:56:05 -0400 Subject: [PATCH 02/32] refactor(torii-libp2p): use cainome + integration test (#2044) * feat: use cainome + integration test * fmt * chore: remove unused imports * Update tests.rs --- Cargo.lock | 1 + crates/torii/libp2p/Cargo.toml | 1 + crates/torii/libp2p/src/server/mod.rs | 85 -------------- crates/torii/libp2p/src/tests.rs | 161 +++++++++++++++++++------- crates/torii/libp2p/src/typed_data.rs | 66 +++-------- 5 files changed, 138 insertions(+), 176 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 96465fc1ff..667854d1df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14268,6 +14268,7 @@ version = "0.7.0-alpha.5" dependencies = [ "anyhow", "async-trait", + "cainome", "chrono", "crypto-bigint", "dojo-test-utils", diff --git a/crates/torii/libp2p/Cargo.toml b/crates/torii/libp2p/Cargo.toml index d95c0ff66a..08c0472988 100644 --- a/crates/torii/libp2p/Cargo.toml +++ b/crates/torii/libp2p/Cargo.toml @@ -26,6 +26,7 @@ starknet.workspace = true thiserror.workspace = true tracing-subscriber = { version = "0.3", features = [ "env-filter" ] } tracing.workspace = true +cainome.workspace = true [dev-dependencies] dojo-test-utils.workspace = true diff --git a/crates/torii/libp2p/src/server/mod.rs b/crates/torii/libp2p/src/server/mod.rs index 3562b5a46f..4a78db033b 100644 --- a/crates/torii/libp2p/src/server/mod.rs +++ b/crates/torii/libp2p/src/server/mod.rs @@ -20,7 +20,6 @@ use libp2p::swarm::{NetworkBehaviour, SwarmEvent}; use libp2p::{identify, identity, noise, ping, relay, tcp, yamux, PeerId, Swarm, Transport}; use libp2p_webrtc as webrtc; use rand::thread_rng; -use serde_json::Number; use starknet::core::types::{BlockId, BlockTag, FunctionCall}; use starknet::core::utils::get_selector_from_name; use starknet::providers::Provider; @@ -692,90 +691,6 @@ fn read_or_create_certificate(path: &Path) -> anyhow::Result { Ok(cert) } -// Deprecated. These should be potentially removed. As Ty -> TypedData is now done -// on the SDKs side -pub fn parse_ty_to_object(ty: &Ty) -> Result, Error> { - match ty { - Ty::Struct(struct_ty) => { - let mut object = IndexMap::new(); - for member in &struct_ty.children { - let mut member_object = IndexMap::new(); - member_object.insert("key".to_string(), PrimitiveType::Bool(member.key)); - member_object.insert( - "type".to_string(), - PrimitiveType::String(ty_to_string_type(&member.ty)), - ); - member_object.insert("value".to_string(), parse_ty_to_primitive(&member.ty)?); - object.insert(member.name.clone(), PrimitiveType::Object(member_object)); - } - Ok(object) - } - _ => Err(Error::InvalidMessageError("Expected Struct type".to_string())), - } -} - -pub fn ty_to_string_type(ty: &Ty) -> String { - match ty { - Ty::Primitive(primitive) => match primitive { - Primitive::U8(_) => "u8".to_string(), - Primitive::U16(_) => "u16".to_string(), - Primitive::U32(_) => "u32".to_string(), - Primitive::USize(_) => "usize".to_string(), - Primitive::U64(_) => "u64".to_string(), - Primitive::U128(_) => "u128".to_string(), - Primitive::U256(_) => "u256".to_string(), - Primitive::Felt252(_) => "felt252".to_string(), - Primitive::ClassHash(_) => "class_hash".to_string(), - Primitive::ContractAddress(_) => "contract_address".to_string(), - Primitive::Bool(_) => "bool".to_string(), - }, - Ty::Struct(_) => "struct".to_string(), - Ty::Tuple(_) => "tuple".to_string(), - Ty::Array(_) => "array".to_string(), - Ty::ByteArray(_) => "bytearray".to_string(), - Ty::Enum(_) => "enum".to_string(), - } -} - -pub fn parse_ty_to_primitive(ty: &Ty) -> Result { - match ty { - Ty::Primitive(primitive) => match primitive { - Primitive::U8(value) => { - Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64)))) - } - Primitive::U16(value) => { - Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64)))) - } - Primitive::U32(value) => { - Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64)))) - } - Primitive::USize(value) => { - Ok(PrimitiveType::Number(Number::from(value.map(|v| v as u64).unwrap_or(0u64)))) - } - Primitive::U64(value) => { - Ok(PrimitiveType::Number(Number::from(value.map(|v| v).unwrap_or(0u64)))) - } - Primitive::U128(value) => Ok(PrimitiveType::String( - value.map(|v| v.to_string()).unwrap_or_else(|| "0".to_string()), - )), - Primitive::U256(value) => Ok(PrimitiveType::String( - value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()), - )), - Primitive::Felt252(value) => Ok(PrimitiveType::String( - value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()), - )), - Primitive::ClassHash(value) => Ok(PrimitiveType::String( - value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()), - )), - Primitive::ContractAddress(value) => Ok(PrimitiveType::String( - value.map(|v| format!("{:#x}", v)).unwrap_or_else(|| "0".to_string()), - )), - Primitive::Bool(value) => Ok(PrimitiveType::Bool(value.unwrap_or(false))), - }, - _ => Err(Error::InvalidMessageError("Expected Primitive type".to_string())), - } -} - #[cfg(test)] mod tests { use tempfile::tempdir; diff --git a/crates/torii/libp2p/src/tests.rs b/crates/torii/libp2p/src/tests.rs index 3d0e5581be..7db5ab677b 100644 --- a/crates/torii/libp2p/src/tests.rs +++ b/crates/torii/libp2p/src/tests.rs @@ -268,20 +268,25 @@ mod test { #[cfg(not(target_arch = "wasm32"))] #[tokio::test] async fn test_client_messaging() -> Result<(), Box> { + use std::time::Duration; + use dojo_test_utils::sequencer::{ get_default_test_starknet_config, SequencerConfig, TestSequencer, }; use dojo_types::schema::{Member, Struct, Ty}; + use dojo_world::contracts::abi::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::FieldElement; + use tokio::select; use tokio::time::sleep; use torii_core::sql::Sql; - use crate::server::{parse_ty_to_object, Relay}; - use crate::typed_data::{Domain, TypedData}; + use crate::server::Relay; + use crate::typed_data::{Domain, Field, SimpleField, TypedData}; use crate::types::Message; let _ = tracing_subscriber::fmt() @@ -300,7 +305,36 @@ mod test { .await; let provider = JsonRpcClient::new(HttpTransport::new(sequencer.url())); - let db = Sql::new(pool.clone(), FieldElement::from_bytes_be(&[0; 32]).unwrap()).await?; + let account = sequencer.raw_account(); + + let mut db = Sql::new(pool.clone(), FieldElement::from_bytes_be(&[0; 32]).unwrap()).await?; + + // Register the model of our Message + db.register_model( + Ty::Struct(Struct { + name: "Message".to_string(), + children: vec![ + Member { + name: "identity".to_string(), + ty: Ty::Primitive(Primitive::ContractAddress(None)), + key: true, + }, + Member { + name: "message".to_string(), + ty: Ty::ByteArray("".to_string()), + key: false, + }, + ], + }), + Layout::Fixed(vec![]), + FieldElement::ZERO, + FieldElement::ZERO, + 0, + 0, + 0, + ) + .await + .unwrap(); // Initialize the relay server let mut relay_server = Relay::new(db, provider, 9900, 9901, None, None)?; @@ -314,27 +348,57 @@ mod test { client.event_loop.lock().await.run().await; }); - let mut data = Struct { name: "Message".to_string(), children: vec![] }; - - data.children.push(Member { - name: "player".to_string(), - ty: dojo_types::schema::Ty::Primitive( - dojo_types::primitive::Primitive::ContractAddress(Some( - FieldElement::from_bytes_be(&[0; 32]).unwrap(), - )), - ), - key: true, - }); - - data.children.push(Member { - name: "message".to_string(), - ty: dojo_types::schema::Ty::Primitive(dojo_types::primitive::Primitive::U8(Some(0))), - key: false, - }); - let mut typed_data = TypedData::new( - IndexMap::new(), - "Message", + IndexMap::from_iter(vec![ + ( + "OffchainMessage".to_string(), + vec![ + Field::SimpleType(SimpleField { + name: "model".to_string(), + r#type: "shortstring".to_string(), + }), + Field::SimpleType(SimpleField { + name: "Message".to_string(), + r#type: "Model".to_string(), + }), + ], + ), + ( + "Model".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(), + }), + ], + ), + ]), + "OffchainMessage", Domain::new("Message", "1", "0x0", Some("1")), IndexMap::new(), ); @@ -346,37 +410,50 @@ mod test { typed_data.message.insert( "Message".to_string(), crate::typed_data::PrimitiveType::Object( - parse_ty_to_object(&Ty::Struct(data.clone())).unwrap(), + vec![ + ( + "identity".to_string(), + crate::typed_data::PrimitiveType::String( + account.account_address.to_string(), + ), + ), + ( + "message".to_string(), + crate::typed_data::PrimitiveType::String("mimi".to_string()), + ), + ] + .into_iter() + .collect(), ), ); + let message_hash = typed_data.encode(account.account_address).unwrap(); + let signature = + SigningKey::from_secret_scalar(account.private_key).sign(&message_hash).unwrap(); + client .command_sender .publish(Message { message: typed_data, - signature_r: FieldElement::from_bytes_be(&[0; 32]).unwrap(), - signature_s: FieldElement::from_bytes_be(&[0; 32]).unwrap(), + signature_r: signature.r, + signature_s: signature.s, }) .await?; sleep(std::time::Duration::from_secs(2)).await; - Ok(()) - // loop { - // select! { - // entity = sqlx::query("SELECT * FROM entities WHERE id = ?") - // .bind(format!("{:#x}", FieldElement::from_bytes_be(&[0; - // 32]).unwrap())).fetch_one(&pool) => { if let Ok(_) = entity { - // 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()); - // } - // } - // } + 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()); + } + } + } } #[cfg(target_arch = "wasm32")] diff --git a/crates/torii/libp2p/src/typed_data.rs b/crates/torii/libp2p/src/typed_data.rs index dc752f751b..733c7ca29d 100644 --- a/crates/torii/libp2p/src/typed_data.rs +++ b/crates/torii/libp2p/src/typed_data.rs @@ -1,11 +1,10 @@ use std::str::FromStr; +use cainome::cairo_serde::ByteArray; use indexmap::IndexMap; use serde::{Deserialize, Serialize}; use serde_json::Number; -use starknet::core::utils::{ - cairo_short_string_to_felt, get_selector_from_name, CairoShortStringToFeltError, -}; +use starknet::core::utils::{cairo_short_string_to_felt, get_selector_from_name}; use starknet_crypto::{poseidon_hash_many, FieldElement}; use crate::errors::Error; @@ -176,39 +175,6 @@ pub fn encode_type(name: &str, types: &IndexMap>) -> Result Result<(Vec, FieldElement, usize), CairoShortStringToFeltError> { - let short_strings: Vec<&str> = split_long_string(target_string); - let remainder = short_strings.last().unwrap_or(&""); - - let mut short_strings_encoded = short_strings - .iter() - .map(|&s| cairo_short_string_to_felt(s)) - .collect::, _>>()?; - - let (pending_word, pending_word_length) = if remainder.is_empty() || remainder.len() == 31 { - (FieldElement::ZERO, 0) - } else { - (short_strings_encoded.pop().unwrap(), remainder.len()) - }; - - Ok((short_strings_encoded, pending_word, pending_word_length)) -} - -fn split_long_string(long_str: &str) -> Vec<&str> { - let mut result = Vec::new(); - - let mut start = 0; - while start < long_str.len() { - let end = (start + 31).min(long_str.len()); - result.push(&long_str[start..end]); - start = end; - } - - result -} - #[derive(Debug, Default)] pub struct Ctx { pub base_type: String, @@ -273,7 +239,7 @@ fn get_hex(value: &str) -> Result { } else { // assume its a short string and encode cairo_short_string_to_felt(value) - .map_err(|_| Error::InvalidMessageError("Invalid short string".to_string())) + .map_err(|e| Error::InvalidMessageError(format!("Invalid shortstring for felt: {}", e))) } } @@ -330,8 +296,11 @@ 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(|_| { - Error::InvalidMessageError(format!("Invalid type {} for selector", r#type)) + hashes.push(get_selector_from_name(&type_hash).map_err(|e| { + Error::InvalidMessageError(format!( + "Invalid type {} for selector: {}", + r#type, e + )) })?); for (field_name, value) in obj { @@ -368,24 +337,23 @@ impl PrimitiveType { "shortstring" => get_hex(string), "string" => { // split the string into short strings and encode - let byte_array = byte_array_from_string(string).map_err(|_| { - Error::InvalidMessageError("Invalid short string".to_string()) + let byte_array = ByteArray::from_string(string).map_err(|e| { + Error::InvalidMessageError(format!("Invalid string for bytearray: {}", e)) })?; - let mut hashes = vec![FieldElement::from(byte_array.0.len())]; + let mut hashes = vec![FieldElement::from(byte_array.data.len())]; - for hash in byte_array.0 { - hashes.push(hash); + for hash in byte_array.data { + hashes.push(hash.felt()); } - hashes.push(byte_array.1); - hashes.push(FieldElement::from(byte_array.2)); + hashes.push(byte_array.pending_word); + hashes.push(FieldElement::from(byte_array.pending_word_len)); Ok(poseidon_hash_many(hashes.as_slice())) } - "selector" => get_selector_from_name(string).map_err(|_| { - Error::InvalidMessageError(format!("Invalid type {} for selector", r#type)) - }), + "selector" => get_selector_from_name(string) + .map_err(|e| Error::InvalidMessageError(format!("Invalid selector: {}", e))), "felt" => get_hex(string), "ContractAddress" => get_hex(string), "ClassHash" => get_hex(string), From 9fcd5abd6ac1b5e3f38742f16643e296f849c788 Mon Sep 17 00:00:00 2001 From: glihm Date: Wed, 12 Jun 2024 14:20:13 -0600 Subject: [PATCH 03/32] fix: fix RPC version checking (#2048) --- bin/sozo/src/commands/migrate.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/bin/sozo/src/commands/migrate.rs b/bin/sozo/src/commands/migrate.rs index 3acb7f25cb..1bf05338a8 100644 --- a/bin/sozo/src/commands/migrate.rs +++ b/bin/sozo/src/commands/migrate.rs @@ -201,8 +201,8 @@ fn is_compatible_version(provided_version: &str, expected_version: &str) -> Resu .map_err(|e| anyhow!("Failed to parse expected version '{}': {}", expected_version, e))?; // Specific backward compatibility rule: 0.6 is compatible with 0.7. - if (provided_ver.major == 0 && provided_ver.minor == 6) - && (expected_ver.major == 0 && expected_ver.minor == 7) + if (provided_ver.major == 0 && provided_ver.minor == 7) + && (expected_ver.major == 0 && expected_ver.minor == 6) { return Ok(true); } @@ -235,7 +235,9 @@ mod tests { #[test] fn test_is_compatible_version_specific_backward_compatibility() { - assert!(is_compatible_version("0.6.0", "0.7.1").unwrap()); + let node_version = "0.7.1"; + let katana_version = "0.6.0"; + assert!(is_compatible_version(node_version, katana_version).unwrap()); } #[test] From 1fe04888932ae429b09939dbbebfde79cdfd4ee1 Mon Sep 17 00:00:00 2001 From: glihm Date: Wed, 12 Jun 2024 17:03:57 -0600 Subject: [PATCH 04/32] fix(ci): add missing path to foundry binaries (#2051) fix: add missing path to foundry binaries --- .devcontainer/Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index ed7155c5c1..66bba6e674 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -18,6 +18,7 @@ RUN echo "deb http://apt.llvm.org/${VARIANT}/ llvm-toolchain-${VARIANT}-17 main" RUN apt-get -y install -t llvm-toolchain-${VARIANT}-17 llvm-17 llvm-17-dev llvm-17-runtime clang-17 clang-tools-17 lld-17 libpolly-17-dev libmlir-17-dev mlir-17-tools RUN curl -L https://foundry.paradigm.xyz/ | bash && . /root/.bashrc && foundryup +ENV PATH="${PATH}:/root/.foundry/bin" # To build Katana with 'native' feature, we need to set the following environment variables ENV MLIR_SYS_170_PREFIX=/usr/lib/llvm-17 From a5f043e39d4cc41da137b0cf20b24a1ebb8b4f77 Mon Sep 17 00:00:00 2001 From: notV4l <122404722+notV4l@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:49:56 +0200 Subject: [PATCH 05/32] [trick] to unlock toriiClient with safari/firefox (#2038) * trick: to unlock toriiClient with safari/firefox * same trick for other subscribers * refactor: send initial stream message directly * chore: avoid sender clone --------- Co-authored-by: Nasr --- crates/torii/grpc/src/client.rs | 32 +++++++++++++++---- .../grpc/src/server/subscriptions/entity.rs | 6 ++++ .../src/server/subscriptions/event_message.rs | 6 ++++ .../src/server/subscriptions/model_diff.rs | 6 ++++ crates/torii/server/src/proxy.rs | 3 +- 5 files changed, 44 insertions(+), 9 deletions(-) diff --git a/crates/torii/grpc/src/client.rs b/crates/torii/grpc/src/client.rs index 4a11e04777..7f34a60209 100644 --- a/crates/torii/grpc/src/client.rs +++ b/crates/torii/grpc/src/client.rs @@ -3,7 +3,7 @@ use std::num::ParseIntError; use futures_util::stream::MapOk; use futures_util::{Stream, StreamExt, TryStreamExt}; -use starknet::core::types::{FromStrError, StateUpdate}; +use starknet::core::types::{FromStrError, StateDiff, StateUpdate}; use starknet_crypto::FieldElement; use crate::proto::world::{ @@ -105,9 +105,9 @@ impl WorldClient { .map_err(Error::Grpc) .map(|res| res.into_inner())?; - Ok(EntityUpdateStreaming(stream.map_ok(Box::new(|res| { - let entity = res.entity.expect("entity must exist"); - entity.try_into().expect("must able to serialize") + Ok(EntityUpdateStreaming(stream.map_ok(Box::new(|res| match res.entity { + Some(entity) => entity.try_into().expect("must able to serialize"), + None => Entity { hashed_keys: FieldElement::ZERO, models: vec![] }, })))) } @@ -144,9 +144,11 @@ impl WorldClient { .map_err(Error::Grpc) .map(|res| res.into_inner())?; - Ok(ModelDiffsStreaming(stream.map_ok(Box::new(|res| { - let update = res.model_update.expect("qed; state update must exist"); - TryInto::::try_into(update).expect("must able to serialize") + Ok(ModelDiffsStreaming(stream.map_ok(Box::new(|res| match res.model_update { + Some(update) => { + TryInto::::try_into(update).expect("must able to serialize") + } + None => empty_state_update(), })))) } } @@ -184,3 +186,19 @@ impl Stream for EntityUpdateStreaming { self.0.poll_next_unpin(cx) } } + +fn empty_state_update() -> StateUpdate { + StateUpdate { + block_hash: FieldElement::ZERO, + new_root: FieldElement::ZERO, + old_root: FieldElement::ZERO, + state_diff: StateDiff { + declared_classes: vec![], + deployed_contracts: vec![], + deprecated_declared_classes: vec![], + nonces: vec![], + replaced_classes: vec![], + storage_diffs: vec![], + }, + } +} diff --git a/crates/torii/grpc/src/server/subscriptions/entity.rs b/crates/torii/grpc/src/server/subscriptions/entity.rs index 1573b5c61f..f9d4ae0d96 100644 --- a/crates/torii/grpc/src/server/subscriptions/entity.rs +++ b/crates/torii/grpc/src/server/subscriptions/entity.rs @@ -20,6 +20,7 @@ use torii_core::types::Entity; use tracing::{error, trace}; use crate::proto; +use crate::proto::world::SubscribeEntityResponse; pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::entity"; @@ -43,6 +44,11 @@ impl EntityManager { let id = rand::thread_rng().gen::(); let (sender, receiver) = channel(1); + // NOTE: unlock issue with firefox/safari + // initially send empty stream message to return from + // initial subscribe call + let _ = sender.send(Ok(SubscribeEntityResponse { entity: None })).await; + self.subscribers.write().await.insert( id, EntitiesSubscriber { hashed_keys: hashed_keys.iter().cloned().collect(), sender }, diff --git a/crates/torii/grpc/src/server/subscriptions/event_message.rs b/crates/torii/grpc/src/server/subscriptions/event_message.rs index 736f88c0f9..67cf1cf172 100644 --- a/crates/torii/grpc/src/server/subscriptions/event_message.rs +++ b/crates/torii/grpc/src/server/subscriptions/event_message.rs @@ -20,6 +20,7 @@ use torii_core::types::EventMessage; use tracing::{error, trace}; use crate::proto; +use crate::proto::world::SubscribeEntityResponse; pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::event_message"; pub struct EventMessagesSubscriber { @@ -42,6 +43,11 @@ impl EventMessageManager { let id = rand::thread_rng().gen::(); let (sender, receiver) = channel(1); + // NOTE: unlock issue with firefox/safari + // initially send empty stream message to return from + // initial subscribe call + let _ = sender.send(Ok(SubscribeEntityResponse { entity: None })).await; + self.subscribers.write().await.insert( id, EventMessagesSubscriber { hashed_keys: hashed_keys.iter().cloned().collect(), sender }, diff --git a/crates/torii/grpc/src/server/subscriptions/model_diff.rs b/crates/torii/grpc/src/server/subscriptions/model_diff.rs index ad257c719c..8e1f4e80cf 100644 --- a/crates/torii/grpc/src/server/subscriptions/model_diff.rs +++ b/crates/torii/grpc/src/server/subscriptions/model_diff.rs @@ -20,6 +20,7 @@ use tracing::{debug, error, trace}; use super::error::SubscriptionError; use crate::proto; +use crate::proto::world::SubscribeModelsResponse; use crate::types::KeysClause; pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::model_diff"; @@ -82,6 +83,11 @@ impl StateDiffManager { .flatten() .collect::>(); + // NOTE: unlock issue with firefox/safari + // initially send empty stream message to return from + // initial subscribe call + let _ = sender.send(Ok(SubscribeModelsResponse { model_update: None })).await; + self.subscribers .write() .await diff --git a/crates/torii/server/src/proxy.rs b/crates/torii/server/src/proxy.rs index df9f4e26f5..23539b5d49 100644 --- a/crates/torii/server/src/proxy.rs +++ b/crates/torii/server/src/proxy.rs @@ -17,7 +17,7 @@ use tower::ServiceBuilder; use tower_http::cors::{AllowOrigin, CorsLayer}; use tracing::error; -const DEFAULT_ALLOW_HEADERS: [&str; 12] = [ +const DEFAULT_ALLOW_HEADERS: [&str; 11] = [ "accept", "origin", "content-type", @@ -27,7 +27,6 @@ const DEFAULT_ALLOW_HEADERS: [&str; 12] = [ "x-grpc-timeout", "x-user-agent", "connection", - "upgrade", "sec-websocket-key", "sec-websocket-version", ]; From 78c88e5c4ffaa81134fb95e783c839efddf8e56b Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Thu, 13 Jun 2024 16:16:30 -0400 Subject: [PATCH 06/32] feat(dojo-bindgen): 2d+ arrays, bytearrays and enums serialization (#2028) * refacotr: handle bytearrays in systems * fix: system gen for calldata * chore: correctly map type * fmt * feat: only generate systems (funcs with no outputs) * compare by u8 * remove unused import * feat: add linq * feat: get index helper for new record enums * chore: fmt * refactor: to handle arrays * refactor: bindgen system gen logic * feat: support 2d+ arrays in system codegen * chore: flat map * chore: reset actions --- crates/dojo-bindgen/src/plugins/unity/mod.rs | 263 +++++++++++++++---- 1 file changed, 214 insertions(+), 49 deletions(-) diff --git a/crates/dojo-bindgen/src/plugins/unity/mod.rs b/crates/dojo-bindgen/src/plugins/unity/mod.rs index 2827519351..45578f2267 100644 --- a/crates/dojo-bindgen/src/plugins/unity/mod.rs +++ b/crates/dojo-bindgen/src/plugins/unity/mod.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use std::path::{Path, PathBuf}; use async_trait::async_trait; -use cainome::parser::tokens::{Composite, CompositeType, Function, Token}; +use cainome::parser::tokens::{Composite, CompositeType, Function, FunctionOutputKind, Token}; use crate::error::BindgenResult; use crate::plugins::BuiltinPlugin; @@ -87,6 +87,32 @@ impl UnityPlugin { ) } + fn contract_imports() -> String { + "using System; +using System.Threading.Tasks; +using Dojo; +using Dojo.Starknet; +using UnityEngine; +using dojo_bindings; +using System.Collections.Generic; +using System.Linq; +using Enum = Dojo.Starknet.Enum; +" + .to_string() + } + + fn model_imports() -> String { + "using System; +using Dojo; +using Dojo.Starknet; +using System.Reflection; +using System.Linq; +using System.Collections.Generic; +using Enum = Dojo.Starknet.Enum; +" + .to_string() + } + // Token should be a struct // This will be formatted into a C# struct // using C# and unity SDK types @@ -116,7 +142,8 @@ public struct {} {{ // This will be formatted into a C# enum // Enum is mapped using index of cairo enum fn format_enum(token: &Composite) -> String { - let mut name_with_generics = token.type_name(); + let name = token.type_name(); + let mut name_with_generics = name.clone(); if !token.generic_args.is_empty() { name_with_generics += &format!( "<{}>", @@ -127,7 +154,7 @@ public struct {} {{ let mut result = format!( " // Type definition for `{}` enum -public abstract record {}() {{", +public abstract record {}() : Enum {{", token.type_path, name_with_generics ); @@ -189,21 +216,23 @@ public class {} : ModelInstance {{ // Handles a model definition and its referenced tokens // Will map all structs and enums to C# types // Will format the model into a C# class - fn handle_model(&self, model: &DojoModel, handled_tokens: &mut Vec) -> String { + fn handle_model( + &self, + model: &DojoModel, + handled_tokens: &mut HashMap, + ) -> String { let mut out = String::new(); out += UnityPlugin::generated_header().as_str(); - out += "using System;\n"; - out += "using Dojo;\n"; - out += "using Dojo.Starknet;\n"; + out += UnityPlugin::model_imports().as_str(); let mut model_struct: Option<&Composite> = None; let tokens = &model.tokens; for token in &tokens.structs { - if handled_tokens.iter().any(|t| t.type_name() == token.type_name()) { + if handled_tokens.contains_key(&token.type_path()) { continue; } - handled_tokens.push(token.to_composite().unwrap().to_owned()); + handled_tokens.insert(token.type_path(), token.to_composite().unwrap().to_owned()); // first index is our model struct if token.type_name() == model.name { @@ -215,11 +244,11 @@ public class {} : ModelInstance {{ } for token in &tokens.enums { - if handled_tokens.iter().any(|t| t.type_name() == token.type_name()) { + if handled_tokens.contains_key(&token.type_path()) { continue; } - handled_tokens.push(token.to_composite().unwrap().to_owned()); + handled_tokens.insert(token.type_path(), token.to_composite().unwrap().to_owned()); out += UnityPlugin::format_enum(token.to_composite().unwrap()).as_str(); } @@ -233,7 +262,145 @@ public class {} : ModelInstance {{ // Formats a system into a C# method used by the contract class // Handled tokens should be a list of all structs and enums used by the contract // Such as a set of referenced tokens from a model - fn format_system(system: &Function, handled_tokens: &[Composite]) -> String { + fn format_system(system: &Function, handled_tokens: &HashMap) -> String { + fn handle_arg_recursive( + arg_name: &str, + token: &Token, + handled_tokens: &HashMap, + // variant name + // if its an enum variant data + enum_variant: Option, + ) -> Vec<( + // formatted arg + String, + // if its an array + bool, + // enum name and variant name + // if its an enum variant data + Option, + )> { + let mapped_type = UnityPlugin::map_type(token); + + match token { + Token::Composite(t) => { + let t = handled_tokens.get(&t.type_path).unwrap_or(t); + + // Need to flatten the struct members. + match t.r#type { + CompositeType::Struct if t.type_name() == "ByteArray" => vec![( + format!("ByteArray.Serialize({}).Select(f => f.Inner)", arg_name), + true, + enum_variant, + )], + CompositeType::Struct => { + let mut tokens = vec![]; + t.inners.iter().for_each(|f| { + tokens.extend(handle_arg_recursive( + &format!("{}.{}", arg_name, f.name), + &f.token, + handled_tokens, + enum_variant.clone(), + )); + }); + + tokens + } + CompositeType::Enum => { + let mut tokens = vec![( + format!("new FieldElement(Enum.GetIndex({})).Inner", arg_name), + false, + enum_variant, + )]; + + t.inners.iter().for_each(|field| { + if let Token::CoreBasic(basic) = &field.token { + // ignore unit type + if basic.type_path == "()" { + return; + } + } + + tokens.extend(handle_arg_recursive( + &format!( + "(({}.{}){}).value", + mapped_type, + field.name.clone(), + arg_name + ), + &if let Token::GenericArg(generic_arg) = &field.token { + let generic_token = t + .generic_args + .iter() + .find(|(name, _)| name == generic_arg) + .unwrap() + .1 + .clone(); + generic_token + } else { + field.token.clone() + }, + handled_tokens, + Some(field.name.clone()), + )) + }); + + tokens + } + CompositeType::Unknown => panic!("Unknown composite type: {:?}", t), + } + } + Token::Array(array) => { + let is_inner_array = matches!(array.inner.as_ref(), Token::Array(_)); + let inner = handle_arg_recursive( + &format!("{arg_name}Item"), + &array.inner, + handled_tokens, + enum_variant.clone(), + ); + + let inners = inner + .into_iter() + .map(|(arg, _, _)| arg) + .collect::>() + .join(", "); + + vec![( + if is_inner_array { + format!( + "{arg_name}.SelectMany({arg_name}Item => new dojo.FieldElement[] \ + {{ }}.Concat({inners}))" + ) + } else { + format!( + "{arg_name}.SelectMany({arg_name}Item => new [] {{ {inners} }})" + ) + }, + true, + enum_variant.clone(), + )] + } + Token::Tuple(tuple) => tuple + .inners + .iter() + .enumerate() + .flat_map(|(idx, token)| { + handle_arg_recursive( + &format!("{}.Item{}", arg_name, idx + 1), + token, + handled_tokens, + enum_variant.clone(), + ) + }) + .collect(), + _ => match mapped_type.as_str() { + "FieldElement" => vec![(format!("{}.Inner", arg_name), false, enum_variant)], + _ => { + vec![(format!("new FieldElement({}).Inner", arg_name), false, enum_variant)] + } + }, + } + } + let args = system .inputs .iter() @@ -244,35 +411,31 @@ public class {} : ModelInstance {{ let calldata = system .inputs .iter() - .map(|arg| { - let token = &arg.1; - let type_name = &arg.0; - - match handled_tokens.iter().find(|t| t.type_name() == token.type_name()) { - Some(t) => { - // Need to flatten the struct members. - match t.r#type { - CompositeType::Struct => t - .inners - .iter() - .map(|field| { - format!("new FieldElement({}.{}).Inner", type_name, field.name) - }) - .collect::>() - .join(",\n "), - _ => { - format!("new FieldElement({}).Inner", type_name) - } + .flat_map(|(name, token)| { + let tokens = handle_arg_recursive(name, token, handled_tokens, None); + + tokens + .iter() + .map(|(arg, is_array, enum_variant)| { + let calldata_op = if *is_array { + format!("calldata.AddRange({arg});") + } else { + format!("calldata.Add({arg});") + }; + + if let Some(variant) = enum_variant { + let mapped_token = UnityPlugin::map_type(token); + let mapped_variant_type = format!("{}.{}", mapped_token, variant); + + format!("if ({name} is {mapped_variant_type}) {calldata_op}",) + } else { + calldata_op } - } - None => match UnityPlugin::map_type(token).as_str() { - "FieldElement" => format!("{}.Inner", type_name), - _ => format!("new FieldElement({}).Inner", type_name), - }, - } + }) + .collect::>() }) .collect::>() - .join(",\n "); + .join("\n\t\t"); format!( " @@ -280,13 +443,14 @@ public class {} : ModelInstance {{ // Returns the transaction hash. Use `WaitForTransaction` to wait for the transaction to be \ confirmed. public async Task {system_name}(Account account{arg_sep}{args}) {{ + List calldata = new List(); + {calldata} + return await account.ExecuteRaw(new dojo.Call[] {{ new dojo.Call{{ to = contractAddress, selector = \"{system_name}\", - calldata = new dojo.FieldElement[] {{ - {calldata} - }} + calldata = calldata.ToArray() }} }}); }} @@ -315,19 +479,20 @@ public class {} : ModelInstance {{ // Will format the contract into a C# class and // all systems into C# methods // Handled tokens should be a list of all structs and enums used by the contract - fn handle_contract(&self, contract: &DojoContract, handled_tokens: &[Composite]) -> String { + fn handle_contract( + &self, + contract: &DojoContract, + handled_tokens: &HashMap, + ) -> String { let mut out = String::new(); out += UnityPlugin::generated_header().as_str(); - out += "using System;\n"; - out += "using System.Threading.Tasks;\n"; - out += "using Dojo;\n"; - out += "using Dojo.Starknet;\n"; - out += "using UnityEngine;\n"; - out += "using dojo_bindings;\n"; + out += UnityPlugin::contract_imports().as_str(); let systems = contract .systems .iter() + // we assume systems dont have outputs + .filter(|s| s.to_function().unwrap().get_output_kind() as u8 == FunctionOutputKind::NoOutput as u8) .map(|system| UnityPlugin::format_system(system.to_function().unwrap(), handled_tokens)) .collect::>() .join("\n\n "); @@ -356,7 +521,7 @@ public class {} : MonoBehaviour {{ impl BuiltinPlugin for UnityPlugin { async fn generate_code(&self, data: &DojoData) -> BindgenResult>> { let mut out: HashMap> = HashMap::new(); - let mut handled_tokens = Vec::::new(); + let mut handled_tokens = HashMap::::new(); // Handle codegen for models for (name, model) in &data.models { From af5be666fb9b5096705b1041d8ebc8c89a55d4bb Mon Sep 17 00:00:00 2001 From: glihm Date: Thu, 13 Jun 2024 17:18:20 -0600 Subject: [PATCH 07/32] feat(core): add state mutability computation from world param (#2049) * rework: add state mutability computation from world param * fix: run fmt * fix: apply review comments * fix: address missing review comment --- crates/dojo-lang/src/contract.rs | 235 +++------- crates/dojo-lang/src/interface.rs | 72 ++-- crates/dojo-lang/src/lib.rs | 1 + crates/dojo-lang/src/plugin_test_data/system | 405 ++++++------------ crates/dojo-lang/src/syntax/mod.rs | 3 + crates/dojo-lang/src/syntax/self_param.rs | 49 +++ crates/dojo-lang/src/syntax/utils.rs | 20 + crates/dojo-lang/src/syntax/world_param.rs | 92 ++++ crates/torii/types-test/src/contracts.cairo | 13 +- .../dojo_examples_actions_actions.json | 15 +- .../dojo_examples_actions_actions.json | 15 +- .../dojo_examples_actions_actions.toml | 4 +- .../manifests/dev/manifest.json | 19 +- .../manifests/dev/manifest.toml | 4 +- examples/spawn-and-move/src/actions.cairo | 18 +- examples/spawn-and-move/src/others.cairo | 2 +- 16 files changed, 439 insertions(+), 528 deletions(-) create mode 100644 crates/dojo-lang/src/syntax/mod.rs create mode 100644 crates/dojo-lang/src/syntax/self_param.rs create mode 100644 crates/dojo-lang/src/syntax/utils.rs create mode 100644 crates/dojo-lang/src/syntax/world_param.rs diff --git a/crates/dojo-lang/src/contract.rs b/crates/dojo-lang/src/contract.rs index fac9667ba0..c2a9c292ff 100644 --- a/crates/dojo-lang/src/contract.rs +++ b/crates/dojo-lang/src/contract.rs @@ -4,37 +4,28 @@ use cairo_lang_defs::patcher::{PatchBuilder, RewriteNode}; use cairo_lang_defs::plugin::{ DynGeneratedFileAuxData, PluginDiagnostic, PluginGeneratedFile, PluginResult, }; -use cairo_lang_diagnostics::Severity; -use cairo_lang_syntax::attribute::structured::{ - Attribute, AttributeArg, AttributeArgVariant, AttributeListStructurize, -}; use cairo_lang_syntax::node::ast::MaybeModuleBody; use cairo_lang_syntax::node::db::SyntaxGroup; use cairo_lang_syntax::node::{ast, ids, Terminal, TypedStablePtr, TypedSyntaxNode}; use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; use dojo_types::system::Dependency; -use crate::plugin::{DojoAuxData, SystemAuxData, DOJO_CONTRACT_ATTR}; +use crate::plugin::{DojoAuxData, SystemAuxData}; +use crate::syntax::world_param::{self, WorldParamInjectionKind}; +use crate::syntax::{self_param, utils as syntax_utils}; -const ALLOW_REF_SELF_ARG: &str = "allow_ref_self"; const DOJO_INIT_FN: &str = "dojo_init"; pub struct DojoContract { diagnostics: Vec, dependencies: HashMap, - do_allow_ref_self: bool, } impl DojoContract { pub fn from_module(db: &dyn SyntaxGroup, module_ast: ast::ItemModule) -> PluginResult { let name = module_ast.name(db).text(db); - let attrs = module_ast.attributes(db).structurize(db); - let dojo_contract_attr = attrs.iter().find(|attr| attr.id.as_str() == DOJO_CONTRACT_ATTR); - let do_allow_ref_self = extract_allow_ref_self(dojo_contract_attr, db).unwrap_or_default(); - - let mut system = - DojoContract { diagnostics: vec![], dependencies: HashMap::new(), do_allow_ref_self }; + let mut system = DojoContract { diagnostics: vec![], dependencies: HashMap::new() }; let mut has_event = false; let mut has_storage = false; let mut has_init = false; @@ -182,14 +173,14 @@ impl DojoContract { let fn_decl = fn_ast.declaration(db); let fn_name = fn_decl.name(db).text(db); - let (params_str, _, world_removed) = self.rewrite_parameters( + let (params_str, was_world_injected) = self.rewrite_parameters( db, fn_decl.signature(db).parameters(db), fn_ast.stable_ptr().untyped(), ); let mut world_read = ""; - if world_removed { + if was_world_injected { world_read = "let world = self.world_dispatcher.read();"; } @@ -303,166 +294,61 @@ impl DojoContract { )] } - /// Gets name, modifiers and type from a function parameter. - pub fn get_parameter_info( - &mut self, - db: &dyn SyntaxGroup, - param: ast::Param, - ) -> (String, String, String) { - let name = param.name(db).text(db).trim().to_string(); - let modifiers = param.modifiers(db).as_syntax_node().get_text(db).trim().to_string(); - let param_type = - param.type_clause(db).ty(db).as_syntax_node().get_text(db).trim().to_string(); - - (name, modifiers, param_type) - } - - /// Check if the function has a self parameter. - /// - /// Returns - /// * a boolean indicating if `self` has to be added, - // * a boolean indicating if there is a `ref self` parameter. - pub fn check_self_parameter( - &mut self, - db: &dyn SyntaxGroup, - param_list: ast::ParamList, - ) -> (bool, bool) { - let mut add_self = true; - let mut has_ref_self = false; - if !param_list.elements(db).is_empty() { - let (param_name, param_modifiers, param_type) = - self.get_parameter_info(db, param_list.elements(db)[0].clone()); - - if param_name.eq(&"self".to_string()) { - if param_modifiers.contains(&"ref".to_string()) - && param_type.eq(&"ContractState".to_string()) - { - has_ref_self = true; - add_self = false; - } - - if param_type.eq(&"@ContractState".to_string()) { - add_self = false; - } - } - }; - - (add_self, has_ref_self) - } - - /// Check if the function has multiple IWorldDispatcher parameters. - /// - /// Returns - /// * a boolean indicating if the function has multiple world dispatchers. - pub fn check_world_dispatcher( - &mut self, - db: &dyn SyntaxGroup, - param_list: ast::ParamList, - ) -> bool { - let mut count = 0; - - param_list.elements(db).iter().for_each(|param| { - let (_, _, param_type) = self.get_parameter_info(db, param.clone()); - - if param_type.eq(&"IWorldDispatcher".to_string()) { - count += 1; - } - }); - - count > 1 - } - /// Rewrites parameter list by: - /// * adding `self` parameter if missing, - /// * removing `world` if present as first parameter (self excluded), as it will be read from - /// the first function statement. + /// * adding `self` parameter based on the `world` parameter mutability. If `world` is not + /// provided, a `View` is assumed. + /// * removing `world` if present as first parameter, as it will be read from the first + /// function statement. /// /// Reports an error in case of: - /// * `ref self`, as systems are supposed to be 100% stateless, - /// * multiple IWorldDispatcher parameters. - /// * the `IWorldDispatcher` is not the first parameter (self excluded) and named 'world'. + /// * `self` used explicitly, + /// * multiple world parameters, + /// * the `world` parameter is not the first parameter and named 'world'. /// /// Returns - /// * the list of parameters in a String - /// * a boolean indicating if `self` has been added - // * a boolean indicating if `world` parameter has been removed + /// * the list of parameters in a String. + /// * true if the world has to be injected (found as the first param). pub fn rewrite_parameters( &mut self, db: &dyn SyntaxGroup, param_list: ast::ParamList, - diagnostic_item: ids::SyntaxStablePtrId, - ) -> (String, bool, bool) { - let (add_self, has_ref_self) = self.check_self_parameter(db, param_list.clone()); - let has_multiple_world_dispatchers = self.check_world_dispatcher(db, param_list.clone()); + fn_diagnostic_item: ids::SyntaxStablePtrId, + ) -> (String, bool) { + self_param::check_parameter(db, ¶m_list, fn_diagnostic_item, &mut self.diagnostics); - let mut world_removed = false; + let world_injection = world_param::parse_world_injection( + db, + param_list.clone(), + fn_diagnostic_item, + &mut self.diagnostics, + ); let mut params = param_list .elements(db) .iter() - .enumerate() - .filter_map(|(idx, param)| { - let (name, modifiers, param_type) = self.get_parameter_info(db, param.clone()); - - if param_type.eq(&"IWorldDispatcher".to_string()) - && modifiers.eq(&"".to_string()) - && !has_multiple_world_dispatchers - { - let has_good_pos = (add_self && idx == 0) || (!add_self && idx == 1); - let has_good_name = name.eq(&"world".to_string()); - - if has_good_pos && has_good_name { - world_removed = true; - None - } else { - if !has_good_pos { - self.diagnostics.push(PluginDiagnostic { - stable_ptr: param.stable_ptr().untyped(), - message: "The IWorldDispatcher parameter must be the first \ - parameter of the function (self excluded)." - .to_string(), - severity: Severity::Error, - }); - } + .filter_map(|param| { + let (name, _, param_type) = syntax_utils::get_parameter_info(db, param.clone()); - if !has_good_name { - self.diagnostics.push(PluginDiagnostic { - stable_ptr: param.stable_ptr().untyped(), - message: "The IWorldDispatcher parameter must be named 'world'." - .to_string(), - severity: Severity::Error, - }); - } - Some(param.as_syntax_node().get_text(db)) - } + // If the param is `IWorldDispatcher`, we don't need to keep it in the param list + // as it is flatten in the first statement. + if world_param::is_world_param(&name, ¶m_type) { + None } else { Some(param.as_syntax_node().get_text(db)) } }) .collect::>(); - if has_multiple_world_dispatchers { - self.diagnostics.push(PluginDiagnostic { - stable_ptr: diagnostic_item, - message: "Only one parameter of type IWorldDispatcher is allowed.".to_string(), - severity: Severity::Error, - }); - } - - if has_ref_self && !self.do_allow_ref_self { - self.diagnostics.push(PluginDiagnostic { - stable_ptr: diagnostic_item, - message: "Functions of dojo::contract cannot have 'ref self' parameter." - .to_string(), - severity: Severity::Error, - }); - } - - if add_self { - params.insert(0, "self: @ContractState".to_string()); + match world_injection { + WorldParamInjectionKind::None | WorldParamInjectionKind::View => { + params.insert(0, "self: @ContractState".to_string()); + } + WorldParamInjectionKind::External => { + params.insert(0, "ref self: ContractState".to_string()); + } } - (params.join(", "), add_self, world_removed) + (params.join(", "), world_injection != WorldParamInjectionKind::None) } /// Rewrites function statements by adding the reading of `world` at first statement. @@ -493,21 +379,23 @@ impl DojoContract { ) -> Vec { let mut rewritten_fn = RewriteNode::from_ast(&fn_ast); - let (params_str, self_added, world_removed) = self.rewrite_parameters( + let (params_str, was_world_injected) = self.rewrite_parameters( db, fn_ast.declaration(db).signature(db).parameters(db), fn_ast.stable_ptr().untyped(), ); - if self_added || world_removed { - let rewritten_params = rewritten_fn - .modify_child(db, ast::FunctionWithBody::INDEX_DECLARATION) - .modify_child(db, ast::FunctionDeclaration::INDEX_SIGNATURE) - .modify_child(db, ast::FunctionSignature::INDEX_PARAMETERS); - rewritten_params.set_str(params_str); - } - - if world_removed { + // We always rewrite the params as the self parameter is added based on the + // world mutability. + let rewritten_params = rewritten_fn + .modify_child(db, ast::FunctionWithBody::INDEX_DECLARATION) + .modify_child(db, ast::FunctionDeclaration::INDEX_SIGNATURE) + .modify_child(db, ast::FunctionSignature::INDEX_PARAMETERS); + rewritten_params.set_str(params_str); + + // If the world was injected, we also need to rewrite the statements of the function + // to ensure the `world` injection is effective. + if was_world_injected { let rewritten_statements = rewritten_fn .modify_child(db, ast::FunctionWithBody::INDEX_BODY) .modify_child(db, ast::ExprBlock::INDEX_STATEMENTS); @@ -557,26 +445,3 @@ impl DojoContract { vec![RewriteNode::Copied(impl_ast.as_syntax_node())] } } - -/// Extract the allow_ref_self attribute. -pub(crate) fn extract_allow_ref_self( - allow_ref_self_attr: Option<&Attribute>, - db: &dyn SyntaxGroup, -) -> Option { - let Some(attr) = allow_ref_self_attr else { - return None; - }; - - #[allow(clippy::collapsible_match)] - match &attr.args[..] { - [AttributeArg { variant: AttributeArgVariant::Unnamed(value), .. }] => match value { - ast::Expr::Path(path) - if path.as_syntax_node().get_text_without_trivia(db) == ALLOW_REF_SELF_ARG => - { - Some(true) - } - _ => None, - }, - _ => None, - } -} diff --git a/crates/dojo-lang/src/interface.rs b/crates/dojo-lang/src/interface.rs index 54205335c0..fc9bf2ef1b 100644 --- a/crates/dojo-lang/src/interface.rs +++ b/crates/dojo-lang/src/interface.rs @@ -5,6 +5,9 @@ use cairo_lang_syntax::node::db::SyntaxGroup; use cairo_lang_syntax::node::{ast, ids, Terminal, TypedStablePtr, TypedSyntaxNode}; use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; +use crate::syntax::self_param; +use crate::syntax::world_param::{self, WorldParamInjectionKind}; + pub struct DojoInterface { diagnostics: Vec, } @@ -77,9 +80,7 @@ impl DojoInterface { } } - /// Rewrites parameter list by adding `self` parameter if missing. - /// - /// Reports an error in case of `ref self` as systems are supposed to be 100% stateless. + /// Rewrites parameter list by adding `self` parameter based on the `world` parameter. pub fn rewrite_parameters( &mut self, db: &dyn SyntaxGroup, @@ -92,50 +93,29 @@ impl DojoInterface { .map(|e| e.as_syntax_node().get_text(db)) .collect::>(); - let mut need_to_add_self = true; - if !params.is_empty() { - let first_param = param_list.elements(db)[0].clone(); - let param_name = first_param.name(db).text(db).to_string(); - - if param_name.eq(&"self".to_string()) { - let param_modifiers = first_param - .modifiers(db) - .elements(db) - .iter() - .map(|e| e.as_syntax_node().get_text(db).trim().to_string()) - .collect::>(); - - let param_type = first_param - .type_clause(db) - .ty(db) - .as_syntax_node() - .get_text(db) - .trim() - .to_string(); - - if param_modifiers.contains(&"ref".to_string()) - && param_type.eq(&"TContractState".to_string()) - { - self.diagnostics.push(PluginDiagnostic { - stable_ptr: diagnostic_item, - message: "Functions of dojo::interface cannot have `ref self` parameter." - .to_string(), - severity: Severity::Error, - }); + self_param::check_parameter(db, ¶m_list, diagnostic_item, &mut self.diagnostics); - need_to_add_self = false; - } - - if param_type.eq(&"@TContractState".to_string()) { - need_to_add_self = false; - } + let world_injection = world_param::parse_world_injection( + db, + param_list, + diagnostic_item, + &mut self.diagnostics, + ); + + match world_injection { + WorldParamInjectionKind::None => { + params.insert(0, "self: @TContractState".to_string()); + } + WorldParamInjectionKind::View => { + params.remove(0); + params.insert(0, "self: @TContractState".to_string()); + } + WorldParamInjectionKind::External => { + params.remove(0); + params.insert(0, "ref self: TContractState".to_string()); } }; - if need_to_add_self { - params.insert(0, "self: @TContractState".to_string()); - } - params.join(", ") } @@ -151,11 +131,13 @@ impl DojoInterface { .modify_child(db, ast::FunctionDeclaration::INDEX_SIGNATURE) .modify_child(db, ast::FunctionSignature::INDEX_PARAMETERS); - rewritten_params.set_str(self.rewrite_parameters( + let params_str = self.rewrite_parameters( db, fn_ast.declaration(db).signature(db).parameters(db), fn_ast.stable_ptr().untyped(), - )); + ); + + rewritten_params.set_str(params_str); vec![rewritten_fn] } } diff --git a/crates/dojo-lang/src/lib.rs b/crates/dojo-lang/src/lib.rs index b76ea602c8..4f7e0e4bca 100644 --- a/crates/dojo-lang/src/lib.rs +++ b/crates/dojo-lang/src/lib.rs @@ -13,6 +13,7 @@ pub mod model; pub mod plugin; pub mod print; pub mod semantics; +pub mod syntax; pub(crate) mod version; // Copy of non pub functions from scarb + extension. diff --git a/crates/dojo-lang/src/plugin_test_data/system b/crates/dojo-lang/src/plugin_test_data/system index c23d1a35a0..f7fbef26bb 100644 --- a/crates/dojo-lang/src/plugin_test_data/system +++ b/crates/dojo-lang/src/plugin_test_data/system @@ -85,81 +85,54 @@ trait IEmptyTrait; trait IFaultyTrait { const ONE: u8; - fn do_ref_self(ref self: TContractState); - #[my_attr] fn do_with_attrs(p1: u8) -> u16; } -#[starknet::interface] -trait IAllowedRefSelf { - fn spawn(ref self: T); -} - -#[dojo::contract(allow_ref_self)] -mod ContractAllowedRefSelf { - #[abi(embed_v0)] - impl AllowedImpl of IAllowedRefSelf { - fn spawn(ref self: ContractState) {} - } -} - #[dojo::interface] trait INominalTrait { - fn do_no_param(); - fn do_no_param_but_self(self: @TContractState); - fn do_params(p1: dojo_examples::models::Direction, p2: u8); - fn do_params_and_self(self: @TContractState, p2: u8); - fn do_return_value(p1: u8) -> u16; + fn do_no_param() -> felt252; + fn do_no_param_but_world(world: @IWorldDispatcher) -> felt252; + fn do_no_param_but_world_ref(ref world: IWorldDispatcher) -> felt252; + fn do_params_no_world(p1: felt252, p2: u8) -> felt252; + fn do_params_and_world(world: @IWorldDispatcher, p2: u8) -> felt252; + fn do_params_and_world_ref(ref world: IWorldDispatcher, p2: u8) -> felt252; } #[dojo::interface] -trait IWorldTrait { +trait IFaultyTrait { + fn do_with_self(self: @ContractState) -> felt252; fn do_with_ref_self(ref self: ContractState) -> felt252; fn do_with_several_world_dispatchers( - world: IWorldDispatcher, vec: Vec2, another_world: IWorldDispatcher - ) -> felt252; - fn do_with_world_not_named_world(another_world: IWorldDispatcher) -> felt252; - fn do_with_self_and_world_not_named_world( - self: @ContractState, another_world: IWorldDispatcher - ); - fn do_with_world_not_first(vec: Vec2, world: IWorldDispatcher) -> felt252; - fn do_with_self_and_world_not_first( - self: @ContractState, vec: Vec2, world: IWorldDispatcher + world: @IWorldDispatcher, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252; + fn do_with_world_not_named_world(another_world: @IWorldDispatcher) -> felt252; + fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252; } #[dojo::contract] mod MyFaultyContract { #[abi(embed_v0)] - impl TestWorldImpl of IWorldTrait { - fn do_with_ref_self(ref self: ContractState) -> felt252 { - 'land' - } - - fn do_with_several_world_dispatchers( - world: IWorldDispatcher, vec: Vec2, another_world: IWorldDispatcher - ) -> felt252 { + impl TestFaultyImpl of IFaultyTrait { + fn do_with_self(ref self: ContractState) -> felt252 { 'land' } - fn do_with_world_not_named_world(another_world: IWorldDispatcher) -> felt252 { + fn do_with_ref_self(ref self: ContractState) -> felt252 { 'land' } - fn do_with_self_and_world_not_named_world( - self: @ContractState, another_world: IWorldDispatcher + fn do_with_several_world_dispatchers( + world: @IWorldDispatcher, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252 { 'land' } - fn do_with_world_not_first(vec: Vec2, world: IWorldDispatcher) -> felt252 { + fn do_with_world_not_named_world(another_world: @IWorldDispatcher) -> felt252 { 'land' } - fn do_with_self_and_world_not_first( - self: @ContractState, vec: Vec2, world: IWorldDispatcher - ) -> felt252 { + fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252 { 'land' } } @@ -173,22 +146,28 @@ mod MyNominalContract { } #[abi(embed_v0)] - impl TestWorldImpl of IWorldTrait { - fn do(vec: Vec2) -> felt252 { + impl TestNominalImpl of INominalTrait { + fn do_no_param() -> felt252 { 'land' } - fn do_with_self(self: @ContractState, vec: Vec2) -> felt252 { + fn do_no_param_but_world(world: @IWorldDispatcher) -> felt252 { 'land' } - fn do_with_world_first(world: IWorldDispatcher, vec: Vec2) -> felt252 { + fn do_no_param_but_world_ref(ref world: IWorldDispatcher) -> felt252 { 'land' } - fn do_with_self_and_world_first( - self: @ContractState, world: IWorldDispatcher, vec: Vec2 - ) -> felt252 { + fn do_params_no_world(p1: felt252, p2: u8) -> felt252 { + 'land' + } + + fn do_params_and_world(world: @IWorldDispatcher, p2: u8) -> felt252 { + 'land' + } + + fn do_params_and_world_ref(ref world: IWorldDispatcher, p2: u8) -> felt252 { 'land' } } @@ -347,40 +326,40 @@ error: Anything other than functions is not supported in a dojo::interface const ONE: u8; ^************^ -error: Functions of dojo::interface cannot have `ref self` parameter. - --> test_src/lib.cairo:82:5 - fn do_ref_self(ref self: TContractState); - ^***************************************^ +error: In a dojo contract or interface, you should use `world: @IWorldDispatcher` instead of `self: @ContractState`. + --> test_src/lib.cairo:98:5 + fn do_with_self(self: @ContractState) -> felt252; + ^***********************************************^ -error: Functions of dojo::contract cannot have 'ref self' parameter. - --> test_src/lib.cairo:130:9 - fn do_with_ref_self(ref self: ContractState) -> felt252 { - ^*******************************************************^ +error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. + --> test_src/lib.cairo:99:5 + fn do_with_ref_self(ref self: ContractState) -> felt252; + ^******************************************************^ -error: Only one parameter of type IWorldDispatcher is allowed. - --> test_src/lib.cairo:134:9 - fn do_with_several_world_dispatchers( - ^***********************************^ +error: World parameter must be the first parameter. + --> test_src/lib.cairo:104:5 + fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252; + ^****************************************************************************^ -error: The IWorldDispatcher parameter must be named 'world'. - --> test_src/lib.cairo:140:42 - fn do_with_world_not_named_world(another_world: IWorldDispatcher) -> felt252 { - ^*****************************^ +error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. + --> test_src/lib.cairo:111:9 + fn do_with_self(ref self: ContractState) -> felt252 { + ^***************************************************^ -error: The IWorldDispatcher parameter must be named 'world'. - --> test_src/lib.cairo:145:35 - self: @ContractState, another_world: IWorldDispatcher - ^*****************************^ +error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. + --> test_src/lib.cairo:115:9 + fn do_with_ref_self(ref self: ContractState) -> felt252 { + ^*******************************************************^ -error: The IWorldDispatcher parameter must be the first parameter of the function (self excluded). - --> test_src/lib.cairo:150:47 - fn do_with_world_not_first(vec: Vec2, world: IWorldDispatcher) -> felt252 { - ^*********************^ +error: World parameter must be the first parameter. + --> test_src/lib.cairo:129:9 + fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252 { + ^*****************************************************************************^ -error: The IWorldDispatcher parameter must be the first parameter of the function (self excluded). - --> test_src/lib.cairo:155:46 - self: @ContractState, vec: Vec2, world: IWorldDispatcher - ^*********************^ +error: World parameter must be a snapshot if `ref` is not used. + --> test_src/lib.cairo:180:5 + fn dojo_init( + ^***********^ error: Unsupported attribute. --> test_src/lib.cairo:1:1 @@ -408,32 +387,27 @@ error: Unsupported attribute. ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:84:5 + --> test_src/lib.cairo:82:5 #[my_attr] ^********^ error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ @@ -673,217 +647,172 @@ error: Unsupported attribute. ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:95:5 - #[abi(embed_v0)] - ^**************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unsupported attribute. - --> test_src/lib.cairo:93:1 -#[dojo::contract(allow_ref_self)] -^*******************************^ - -error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:128:5 + --> test_src/lib.cairo:109:5 #[abi(embed_v0)] ^**************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:126:1 + --> test_src/lib.cairo:107:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:169:5 + --> test_src/lib.cairo:142:5 #[abi(embed_v0)] ^**************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:162:1 + --> test_src/lib.cairo:135:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:199:1 + --> test_src/lib.cairo:178:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:216:1 + --> test_src/lib.cairo:195:1 #[dojo::contract] ^***************^ @@ -901,11 +830,6 @@ mod testcomponent2 { struct Storage {} } -#[starknet::interface] -trait IAllowedRefSelf { - fn spawn(ref self: T); -} - #[starknet::contract] mod spawn { use dojo::world; @@ -1210,95 +1134,31 @@ impl EventDrop of core::traits::Drop::; #[starknet::interface] trait IFaultyTrait { - fn do_ref_self(ref self: TContractState); - #[my_attr] fn do_with_attrs(self: @TContractState, p1: u8) -> u16; } - #[starknet::contract] - mod ContractAllowedRefSelf { - use dojo::world; - use dojo::world::IWorldDispatcher; - use dojo::world::IWorldDispatcherTrait; - use dojo::world::IWorldProvider; - use dojo::world::IDojoResourceProvider; - - #[abi(embed_v0)] - impl DojoResourceProviderImpl of IDojoResourceProvider { - fn dojo_resource(self: @ContractState) -> felt252 { - 'ContractAllowedRefSelf' - } - } - - #[abi(embed_v0)] - impl WorldProviderImpl of IWorldProvider { - fn world(self: @ContractState) -> IWorldDispatcher { - self.world_dispatcher.read() - } - } - - #[abi(embed_v0)] - impl UpgradableImpl = dojo::components::upgradeable::upgradeable::UpgradableImpl; - - #[abi(embed_v0)] - impl AllowedImpl of IAllowedRefSelf { - fn spawn(ref self: ContractState) {} - } - - #[starknet::interface] - trait IDojoInit { - fn dojo_init(self: @ContractState); - } - - #[abi(embed_v0)] - impl IDojoInitImpl of IDojoInit { - fn dojo_init(self: @ContractState) { - assert(starknet::get_caller_address() == self.world().contract_address, 'Only world can init'); - } - } - - #[event] - #[derive(Drop, starknet::Event)] - enum Event { - UpgradeableEvent: dojo::components::upgradeable::upgradeable::Event, - } - - #[storage] - struct Storage { - world_dispatcher: IWorldDispatcher, - #[substorage(v0)] - upgradeable: dojo::components::upgradeable::upgradeable::Storage, - } -impl EventDrop of core::traits::Drop::; - - } - #[starknet::interface] trait INominalTrait { - fn do_no_param(self: @TContractState); - fn do_no_param_but_self(self: @TContractState); - fn do_params(self: @TContractState, p1: dojo_examples::models::Direction, p2: u8); - fn do_params_and_self(self: @TContractState, p2: u8); - fn do_return_value(self: @TContractState, p1: u8) -> u16; + fn do_no_param(self: @TContractState) -> felt252; + fn do_no_param_but_world(self: @TContractState) -> felt252; + fn do_no_param_but_world_ref(ref self: TContractState) -> felt252; + fn do_params_no_world(self: @TContractState, p1: felt252, p2: u8) -> felt252; + fn do_params_and_world(self: @TContractState, p2: u8) -> felt252; + fn do_params_and_world_ref(ref self: TContractState, p2: u8) -> felt252; } #[starknet::interface] - trait IWorldTrait { - fn do_with_ref_self(self: @TContractState, ref self: ContractState) -> felt252; + trait IFaultyTrait { + fn do_with_self(self: @TContractState, self: @ContractState) -> felt252; + fn do_with_ref_self(self: @TContractState, ref self: ContractState) -> felt252; fn do_with_several_world_dispatchers( -self: @TContractState, world: IWorldDispatcher, vec: Vec2, another_world: IWorldDispatcher - ) -> felt252; - fn do_with_world_not_named_world(self: @TContractState, another_world: IWorldDispatcher) -> felt252; - fn do_with_self_and_world_not_named_world( -self: @TContractState, self: @ContractState, another_world: IWorldDispatcher - ); - fn do_with_world_not_first(self: @TContractState, vec: Vec2, world: IWorldDispatcher) -> felt252; - fn do_with_self_and_world_not_first( -self: @TContractState, self: @ContractState, vec: Vec2, world: IWorldDispatcher +self: @TContractState, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252; + fn do_with_world_not_named_world(self: @TContractState, another_world: @IWorldDispatcher) -> felt252; + fn do_with_world_not_first(self: @TContractState, vec: Vec2, ref world: IWorldDispatcher) -> felt252; } @@ -1328,34 +1188,27 @@ self: @TContractState, self: @ContractState, vec: Vec2, world: IWorldDis impl UpgradableImpl = dojo::components::upgradeable::upgradeable::UpgradableImpl; #[abi(embed_v0)] - impl TestWorldImpl of IWorldTrait { - fn do_with_ref_self(ref self: ContractState) -> felt252 { + impl TestFaultyImpl of IFaultyTrait { + fn do_with_self(self: @ContractState, ref self: ContractState) -> felt252 { 'land' } - fn do_with_several_world_dispatchers( -self: @ContractState, world: IWorldDispatcher, vec: Vec2, another_world: IWorldDispatcher - ) -> felt252 { - 'land' - } - - fn do_with_world_not_named_world(self: @ContractState, another_world: IWorldDispatcher) -> felt252 { + fn do_with_ref_self(self: @ContractState, ref self: ContractState) -> felt252 { 'land' } - fn do_with_self_and_world_not_named_world( - self: @ContractState, another_world: IWorldDispatcher + fn do_with_several_world_dispatchers( +self: @ContractState, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252 { +let world = self.world_dispatcher.read(); 'land' } - fn do_with_world_not_first(self: @ContractState, vec: Vec2, world: IWorldDispatcher) -> felt252 { + fn do_with_world_not_named_world(self: @ContractState, another_world: @IWorldDispatcher) -> felt252 { 'land' } - fn do_with_self_and_world_not_first( - self: @ContractState, vec: Vec2, world: IWorldDispatcher - ) -> felt252 { + fn do_with_world_not_first(self: @ContractState, vec: Vec2) -> felt252 { 'land' } } @@ -1419,23 +1272,31 @@ impl EventDrop of core::traits::Drop::; } #[abi(embed_v0)] - impl TestWorldImpl of IWorldTrait { - fn do(self: @ContractState, vec: Vec2) -> felt252 { + impl TestNominalImpl of INominalTrait { + fn do_no_param(self: @ContractState) -> felt252 { + 'land' + } + + fn do_no_param_but_world(self: @ContractState) -> felt252 { +let world = self.world_dispatcher.read(); + 'land' + } + + fn do_no_param_but_world_ref(ref self: ContractState) -> felt252 { +let world = self.world_dispatcher.read(); 'land' } - fn do_with_self(self: @ContractState, vec: Vec2) -> felt252 { + fn do_params_no_world(self: @ContractState, p1: felt252, p2: u8) -> felt252 { 'land' } - fn do_with_world_first(self: @ContractState, vec: Vec2) -> felt252 { + fn do_params_and_world(self: @ContractState, p2: u8) -> felt252 { let world = self.world_dispatcher.read(); 'land' } - fn do_with_self_and_world_first( - self: @ContractState, vec: Vec2 - ) -> felt252 { + fn do_params_and_world_ref(ref self: ContractState, p2: u8) -> felt252 { let world = self.world_dispatcher.read(); 'land' } diff --git a/crates/dojo-lang/src/syntax/mod.rs b/crates/dojo-lang/src/syntax/mod.rs new file mode 100644 index 0000000000..cfd40715a2 --- /dev/null +++ b/crates/dojo-lang/src/syntax/mod.rs @@ -0,0 +1,3 @@ +pub mod self_param; +pub mod utils; +pub mod world_param; diff --git a/crates/dojo-lang/src/syntax/self_param.rs b/crates/dojo-lang/src/syntax/self_param.rs new file mode 100644 index 0000000000..2f21ae7522 --- /dev/null +++ b/crates/dojo-lang/src/syntax/self_param.rs @@ -0,0 +1,49 @@ +use cairo_lang_defs::plugin::PluginDiagnostic; +use cairo_lang_diagnostics::Severity; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{ast, ids}; + +use crate::syntax::utils as syntax_utils; + +const SELF_PARAM_NAME: &str = "self"; + +/// Checks if the given function parameter is using `self` instead of `world` param. +/// Adds diagnostic if that case. +/// +/// # Arguments +/// +/// - `db` - The syntax group. +/// - `param_list` - The parameter list of the function. +/// - `fn_diagnostic_item` - The diagnostic item of the function. +/// - `diagnostics` - The diagnostics vector. +pub fn check_parameter( + db: &dyn SyntaxGroup, + param_list: &ast::ParamList, + fn_diagnostic_item: ids::SyntaxStablePtrId, + diagnostics: &mut Vec, +) { + if param_list.elements(db).is_empty() { + return; + } + + let param_0 = param_list.elements(db)[0].clone(); + let (name, modifier, _) = syntax_utils::get_parameter_info(db, param_0.clone()); + + if name.eq(SELF_PARAM_NAME) { + let (expected, actual) = if modifier.eq(&"ref".to_string()) { + ("ref world: IWorldDispatcher", "ref self: ContractState") + } else { + ("world: @IWorldDispatcher", "self: @ContractState") + }; + + diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: format!( + "In a dojo contract or interface, you should use `{}` instead of `{}`.", + expected, actual + ) + .to_string(), + severity: Severity::Error, + }); + } +} diff --git a/crates/dojo-lang/src/syntax/utils.rs b/crates/dojo-lang/src/syntax/utils.rs new file mode 100644 index 0000000000..b4bf5298a1 --- /dev/null +++ b/crates/dojo-lang/src/syntax/utils.rs @@ -0,0 +1,20 @@ +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{ast, Terminal, TypedSyntaxNode}; + +/// Gets the name, modifiers and type of a function parameter. +/// +/// # Arguments +/// +/// * `db` - The syntax group. +/// * `param` - The parameter. +/// +/// # Returns +/// +/// * A tuple containing the name, modifiers and type of the parameter. +pub fn get_parameter_info(db: &dyn SyntaxGroup, param: ast::Param) -> (String, String, String) { + let name = param.name(db).text(db).trim().to_string(); + let modifiers = param.modifiers(db).as_syntax_node().get_text(db).trim().to_string(); + let param_type = param.type_clause(db).ty(db).as_syntax_node().get_text(db).trim().to_string(); + + (name, modifiers, param_type) +} diff --git a/crates/dojo-lang/src/syntax/world_param.rs b/crates/dojo-lang/src/syntax/world_param.rs new file mode 100644 index 0000000000..aac7939770 --- /dev/null +++ b/crates/dojo-lang/src/syntax/world_param.rs @@ -0,0 +1,92 @@ +use cairo_lang_defs::plugin::PluginDiagnostic; +use cairo_lang_diagnostics::Severity; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{ast, ids}; + +use super::utils as syntax_utils; + +const WORLD_PARAM_NAME: &str = "world"; +const WORLD_PARAM_TYPE: &str = "IWorldDispatcher"; +const WORLD_PARAM_TYPE_SNAPSHOT: &str = "@IWorldDispatcher"; + +#[derive(Debug, PartialEq, Eq)] +pub enum WorldParamInjectionKind { + None, + View, + External, +} + +/// Checks if the given parameter is the `world` parameter. +/// +/// The `world` must be named `world`, and be placed first in the argument list. +pub fn is_world_param(param_name: &str, param_type: &str) -> bool { + param_name == WORLD_PARAM_NAME + && (param_type == WORLD_PARAM_TYPE || param_type == WORLD_PARAM_TYPE_SNAPSHOT) +} + +/// Extracts the state mutability of a function from the `world` parameter. +/// +/// Checks if the function has only one `world` parameter (or None). +/// The `world` must be named `world`, and be placed first in the argument list. +/// +/// `fn func1(ref world)` // would be external. +/// `fn func2(world)` // would be view. +/// `fn func3()` // would be view. +/// +/// Returns +/// * The [`WorldParamInjectionKind`] determined from the function's params list. +pub fn parse_world_injection( + db: &dyn SyntaxGroup, + param_list: ast::ParamList, + fn_diagnostic_item: ids::SyntaxStablePtrId, + diagnostics: &mut Vec, +) -> WorldParamInjectionKind { + let mut has_world_injected = false; + let mut injection_kind = WorldParamInjectionKind::None; + + param_list.elements(db).iter().enumerate().for_each(|(idx, param)| { + let (name, modifiers, param_type) = syntax_utils::get_parameter_info(db, param.clone()); + + if !is_world_param(&name, ¶m_type) { + return; + } + + if has_world_injected { + diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: "Only one world parameter is allowed".to_string(), + severity: Severity::Error, + }); + + return; + } else { + has_world_injected = true; + } + + if idx != 0 { + diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: "World parameter must be the first parameter.".to_string(), + severity: Severity::Error, + }); + + return; + } + + if modifiers.contains(&"ref".to_string()) { + injection_kind = WorldParamInjectionKind::External; + } else { + injection_kind = WorldParamInjectionKind::View; + + if param_type == WORLD_PARAM_TYPE { + diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: "World parameter must be a snapshot if `ref` is not used.".to_string(), + severity: Severity::Error, + }); + } + } + }); + + injection_kind +} diff --git a/crates/torii/types-test/src/contracts.cairo b/crates/torii/types-test/src/contracts.cairo index 821e8f957a..df0ef8be39 100644 --- a/crates/torii/types-test/src/contracts.cairo +++ b/crates/torii/types-test/src/contracts.cairo @@ -1,9 +1,9 @@ use starknet::{ContractAddress, ClassHash}; -#[starknet::interface] -trait IRecords { - fn create(self: @TContractState, num_records: u8); - fn delete(self: @TContractState, record_id: u32); +#[dojo::interface] +trait IRecords { + fn create(ref world: IWorldDispatcher, num_records: u8); + fn delete(ref world: IWorldDispatcher, record_id: u32); } #[dojo::contract] @@ -33,8 +33,7 @@ mod records { #[abi(embed_v0)] impl RecordsImpl of IRecords { - fn create(self: @ContractState, num_records: u8) { - let world = self.world_dispatcher.read(); + fn create(ref world: IWorldDispatcher, num_records: u8) { let mut record_idx = 0; loop { @@ -118,7 +117,7 @@ mod records { return (); } // Implemment fn delete, input param: record_id - fn delete(self: @ContractState, record_id: u32) { + fn delete(ref world: IWorldDispatcher, record_id: u32) { let world = self.world_dispatcher.read(); let (record, record_sibling) = get!(world, record_id, (Record, RecordSibling)); let subrecord_id = record_id + 1; diff --git a/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json index 21aed968a7..0882f7c56d 100644 --- a/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json +++ b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json @@ -182,7 +182,7 @@ "name": "spawn", "inputs": [], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -194,7 +194,7 @@ } ], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -206,6 +206,17 @@ } ], "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_player_position", + "inputs": [], + "outputs": [ + { + "type": "dojo_examples::models::Position" + } + ], "state_mutability": "view" } ] diff --git a/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json index 21aed968a7..0882f7c56d 100644 --- a/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json +++ b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json @@ -182,7 +182,7 @@ "name": "spawn", "inputs": [], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -194,7 +194,7 @@ } ], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -206,6 +206,17 @@ } ], "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_player_position", + "inputs": [], + "outputs": [ + { + "type": "dojo_examples::models::Position" + } + ], "state_mutability": "view" } ] diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml index 09f30e5dfa..405be86d28 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" -original_class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" +original_class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" base_class_hash = "0x0" abi = "manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/manifest.json b/examples/spawn-and-move/manifests/dev/manifest.json index ecf5e24f79..0b6a6af2fb 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.json +++ b/examples/spawn-and-move/manifests/dev/manifest.json @@ -1020,8 +1020,8 @@ { "kind": "DojoContract", "address": "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af", - "class_hash": "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767", - "original_class_hash": "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767", + "class_hash": "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d", + "original_class_hash": "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d", "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", "abi": [ { @@ -1207,7 +1207,7 @@ "name": "spawn", "inputs": [], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -1219,7 +1219,7 @@ } ], "outputs": [], - "state_mutability": "view" + "state_mutability": "external" }, { "type": "function", @@ -1231,6 +1231,17 @@ } ], "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_player_position", + "inputs": [], + "outputs": [ + { + "type": "dojo_examples::models::Position" + } + ], "state_mutability": "view" } ] diff --git a/examples/spawn-and-move/manifests/dev/manifest.toml b/examples/spawn-and-move/manifests/dev/manifest.toml index 0e32561e97..601c02ab1b 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/manifest.toml @@ -22,8 +22,8 @@ name = "dojo::base::base" [[contracts]] kind = "DojoContract" address = "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af" -class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" -original_class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" +original_class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" abi = "manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index 65dc16c55c..143696ed80 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -2,9 +2,10 @@ use dojo_examples::models::{Direction, Position, Vec2}; #[dojo::interface] trait IActions { - fn spawn(); - fn move(direction: Direction); - fn set_player_config(name: ByteArray); + fn spawn(ref world: IWorldDispatcher); + fn move(ref world: IWorldDispatcher, direction: Direction); + fn set_player_config(ref world: IWorldDispatcher, name: ByteArray); + fn get_player_position(world: @IWorldDispatcher) -> Position; } #[dojo::interface] @@ -61,7 +62,7 @@ mod actions { #[abi(embed_v0)] impl ActionsImpl of IActions { // ContractState is defined by system decorator expansion - fn spawn(world: IWorldDispatcher) { + fn spawn(ref world: IWorldDispatcher) { let player = get_caller_address(); let position = get!(world, player, (Position)); @@ -76,7 +77,7 @@ mod actions { ); } - fn move(world: IWorldDispatcher, direction: Direction) { + fn move(ref world: IWorldDispatcher, direction: Direction) { let player = get_caller_address(); let (mut position, mut moves) = get!(world, player, (Position, Moves)); moves.remaining -= 1; @@ -86,7 +87,7 @@ mod actions { emit!(world, (Moved { player, direction })); } - fn set_player_config(world: IWorldDispatcher, name: ByteArray) { + fn set_player_config(ref world: IWorldDispatcher, name: ByteArray) { let player = get_caller_address(); let items = array![ @@ -97,6 +98,11 @@ mod actions { set!(world, (config)); } + + fn get_player_position(world: @IWorldDispatcher) -> Position { + let player = get_caller_address(); + get!(world, player, (Position)) + } } } diff --git a/examples/spawn-and-move/src/others.cairo b/examples/spawn-and-move/src/others.cairo index 0f27d036a8..8b64df6a23 100644 --- a/examples/spawn-and-move/src/others.cairo +++ b/examples/spawn-and-move/src/others.cairo @@ -16,7 +16,7 @@ mod others { fn dojo_init( - world: IWorldDispatcher, + world: @IWorldDispatcher, actions_address: ContractAddress, actions_class: ClassHash, value: u8 From 0b8b0e5c50888233bfb47763845e0ff2bc1d3f22 Mon Sep 17 00:00:00 2001 From: lambda-0x <0xlambda@protonmail.com> Date: Fri, 14 Jun 2024 05:22:40 +0530 Subject: [PATCH 08/32] feat: ability to skip migration of certain contracts/models (#2026) * initial commit * Revert "initial commit" This reverts commit 2975876f484f03a62ea584ea2061bdc16360d287. * implement skip_migration logic in DojoMetadata so it is profile specific * do a clean build and migrate * fix tests * fix lints * fix more tests * fix more lints * update dev to use skip_migration * abstract out skipping logic * clean old manifest times during build to remove unused manifets * update example * fix tests * add test for remove_items * fix: use world dispatcher snapshot --------- Co-authored-by: glihm --- .gitignore | 1 + Cargo.lock | 3 + bin/sozo/src/commands/build.rs | 21 +- bin/sozo/src/commands/clean.rs | 8 +- bin/sozo/src/commands/dev.rs | 14 +- bin/sozo/src/commands/migrate.rs | 17 +- bin/sozo/tests/register_test.rs | 9 +- crates/dojo-bindgen/Cargo.toml | 4 + crates/dojo-bindgen/src/lib.rs | 41 +- .../src/plugins/typescript_v2/mod.rs | 21 +- crates/dojo-test-utils/src/migration.rs | 5 + crates/dojo-world/src/contracts/model_test.rs | 8 +- crates/dojo-world/src/contracts/world_test.rs | 18 +- .../dojo-world/src/manifest/manifest_test.rs | 63 +- crates/dojo-world/src/manifest/mod.rs | 21 +- crates/dojo-world/src/metadata.rs | 9 +- crates/dojo-world/src/metadata_test.rs | 5 + crates/sozo/ops/src/migration/mod.rs | 9 +- crates/sozo/ops/src/migration/utils.rs | 5 + crates/torii/core/src/sql_test.rs | 11 +- crates/torii/graphql/src/tests/mod.rs | 21 +- crates/torii/grpc/Cargo.toml | 1 + .../grpc/src/server/tests/entities_test.rs | 20 +- examples/spawn-and-move/Scarb.toml | 26 + .../dojo_examples_mock_token_mock_token.json | 133 + .../dojo_examples_models_mock_token.json | 363 ++ .../dojo_examples_mock_token_mock_token.json | 133 + .../dojo_examples_models_mock_token.json | 363 ++ .../dojo_examples_mock_token_mock_token.toml | 10 + .../dojo_examples_models_mock_token.toml | 15 + .../manifests/dev/manifest.json | 526 +++ .../manifests/dev/manifest.toml | 30 + .../dojo_examples_actions_actions.json | 290 ++ .../dojo_examples_mock_token_mock_token.json | 133 + .../dojo_examples_others_others.json | 146 + .../release/abis/base/dojo_world_world.json | 996 +++++ .../dojo_examples_actions_actions_moved.json | 389 ++ .../models/dojo_examples_models_message.json | 371 ++ .../dojo_examples_models_mock_token.json | 363 ++ .../models/dojo_examples_models_moves.json | 393 ++ .../dojo_examples_models_player_config.json | 385 ++ .../models/dojo_examples_models_position.json | 377 ++ ...es_others_others_contract_initialized.json | 367 ++ .../dojo_examples_actions_actions.json | 290 ++ .../dojo_examples_others_others.json | 146 + .../abis/deployments/dojo_world_world.json | 996 +++++ .../dojo_examples_actions_actions_moved.json | 389 ++ .../dojo_examples_models_emote_message.json | 389 ++ .../models/dojo_examples_models_message.json | 371 ++ .../models/dojo_examples_models_moves.json | 393 ++ .../dojo_examples_models_player_config.json | 385 ++ .../models/dojo_examples_models_position.json | 377 ++ ...es_others_others_contract_initialized.json | 367 ++ .../dojo_examples_actions_actions.toml | 10 + .../dojo_examples_mock_token_mock_token.toml | 10 + .../dojo_examples_others_others.toml | 10 + .../release/base/dojo_base_base.toml | 4 + .../release/base/dojo_world_world.toml | 5 + .../dojo_examples_actions_actions_moved.toml | 15 + .../models/dojo_examples_models_message.toml | 25 + .../dojo_examples_models_mock_token.toml | 15 + .../models/dojo_examples_models_moves.toml | 20 + .../dojo_examples_models_player_config.toml | 25 + .../models/dojo_examples_models_position.toml | 15 + ...es_others_others_contract_initialized.toml | 20 + .../manifests/release/manifest.json | 3910 +++++++++++++++++ .../manifests/release/manifest.toml | 185 + .../dojo_examples_actions_actions.toml | 4 + .../dojo_examples_others_others.toml | 8 + .../release/overlays/dojo_base_base.toml | 1 + .../release/overlays/dojo_world_world.toml | 1 + .../dojo_examples_actions_actions_moved.toml | 1 + .../models/dojo_examples_models_message.toml | 1 + .../dojo_examples_models_mock_token.toml | 1 + .../models/dojo_examples_models_moves.toml | 1 + .../dojo_examples_models_player_config.toml | 1 + .../models/dojo_examples_models_position.toml | 1 + ...es_others_others_contract_initialized.toml | 1 + examples/spawn-and-move/src/lib.cairo | 1 + examples/spawn-and-move/src/mock_token.cairo | 11 + examples/spawn-and-move/src/models.cairo | 8 + 81 files changed, 14494 insertions(+), 63 deletions(-) create mode 100644 examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_mock_token_mock_token.json create mode 100644 examples/spawn-and-move/manifests/dev/abis/base/models/dojo_examples_models_mock_token.json create mode 100644 examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_mock_token_mock_token.json create mode 100644 examples/spawn-and-move/manifests/dev/abis/deployments/models/dojo_examples_models_mock_token.json create mode 100644 examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_mock_token_mock_token.toml create mode 100644 examples/spawn-and-move/manifests/dev/base/models/dojo_examples_models_mock_token.toml create mode 100644 examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_actions_actions.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_mock_token_mock_token.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_others_others.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/dojo_world_world.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_actions_actions_moved.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_message.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_mock_token.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_moves.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_player_config.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_position.json create mode 100644 examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_others_others_contract_initialized.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_actions_actions.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_others_others.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/dojo_world_world.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_actions_actions_moved.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_emote_message.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_message.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_moves.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_player_config.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_position.json create mode 100644 examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_others_others_contract_initialized.json create mode 100644 examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_actions_actions.toml create mode 100644 examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_mock_token_mock_token.toml create mode 100644 examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_others_others.toml create mode 100644 examples/spawn-and-move/manifests/release/base/dojo_base_base.toml create mode 100644 examples/spawn-and-move/manifests/release/base/dojo_world_world.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_actions_actions_moved.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_message.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_mock_token.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_moves.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_player_config.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_position.toml create mode 100644 examples/spawn-and-move/manifests/release/base/models/dojo_examples_others_others_contract_initialized.toml create mode 100644 examples/spawn-and-move/manifests/release/manifest.json create mode 100644 examples/spawn-and-move/manifests/release/manifest.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_actions_actions.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_others_others.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/dojo_base_base.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/dojo_world_world.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_actions_actions_moved.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_message.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_mock_token.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_moves.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_player_config.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_position.toml create mode 100644 examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_others_others_contract_initialized.toml create mode 100644 examples/spawn-and-move/src/mock_token.cairo diff --git a/.gitignore b/.gitignore index 6498958892..09a5b8fd5f 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ crates/benches/bench_results.txt **/generated .vscode bindings +justfile diff --git a/Cargo.lock b/Cargo.lock index 667854d1df..877b081274 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4584,7 +4584,9 @@ dependencies = [ "camino", "chrono", "convert_case 0.6.0", + "dojo-test-utils", "dojo-world", + "scarb", "serde", "serde_json", "starknet", @@ -14224,6 +14226,7 @@ name = "torii-grpc" version = "0.7.0-alpha.5" dependencies = [ "bytes", + "camino", "crypto-bigint", "dojo-test-utils", "dojo-types", diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index e278e693d0..b94785575e 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -2,6 +2,8 @@ use anyhow::{Context, Result}; use clap::Args; use dojo_bindgen::{BuiltinPlugins, PluginManager}; use dojo_lang::scarb_internal::compile_workspace; +use dojo_world::manifest::MANIFESTS_DIR; +use dojo_world::metadata::dojo_metadata_from_workspace; use prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE; use prettytable::{format, Cell, Row, Table}; use scarb::core::{Config, TargetKind}; @@ -9,6 +11,8 @@ use scarb::ops::{CompileOpts, FeaturesOpts, FeaturesSelector}; use sozo_ops::statistics::{get_contract_statistics_for_dir, ContractStatistics}; use tracing::trace; +use crate::commands::clean::CleanArgs; + const BYTECODE_SIZE_LABEL: &str = "Bytecode size [in felts]\n(Sierra, Casm)"; const CONTRACT_CLASS_SIZE_LABEL: &str = "Contract Class size [in bytes]\n(Sierra, Casm)"; @@ -39,6 +43,18 @@ pub struct BuildArgs { impl BuildArgs { pub fn run(self, config: &Config) -> Result<()> { + let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; + + let profile_name = + ws.current_profile().expect("Scarb profile is expected at this point.").to_string(); + + // Manifest path is always a file, we can unwrap safely to get the + // parent folder. + let manifest_dir = ws.manifest_path().parent().unwrap().to_path_buf(); + + let profile_dir = manifest_dir.join(MANIFESTS_DIR).join(profile_name); + CleanArgs::clean_manifests(&profile_dir)?; + let features_opts = FeaturesOpts { features: FeaturesSelector::AllFeatures, no_default_features: false }; @@ -110,9 +126,12 @@ impl BuildArgs { }; trace!(pluginManager=?bindgen, "Generating bindings."); + let ws = scarb::ops::read_workspace(config.manifest_path(), config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + tokio::runtime::Runtime::new() .unwrap() - .block_on(bindgen.generate()) + .block_on(bindgen.generate(dojo_metadata.skip_migration)) .expect("Error generating bindings"); Ok(()) diff --git a/bin/sozo/src/commands/clean.rs b/bin/sozo/src/commands/clean.rs index 7d02a03834..41da4a1921 100644 --- a/bin/sozo/src/commands/clean.rs +++ b/bin/sozo/src/commands/clean.rs @@ -21,7 +21,7 @@ impl CleanArgs { /// # Arguments /// /// * `profile_dir` - The directory where the profile files are located. - pub fn clean_manifests(&self, profile_dir: &Utf8PathBuf) -> Result<()> { + pub fn clean_manifests(profile_dir: &Utf8PathBuf) -> Result<()> { trace!(?profile_dir, "Cleaning manifests."); let dirs = vec![profile_dir.join(BASE_DIR), profile_dir.join(ABIS_DIR).join(BASE_DIR)]; @@ -51,7 +51,7 @@ impl CleanArgs { // By default, this command cleans the build manifests and scarb artifacts. trace!("Cleaning Scarb artifacts and build manifests."); scarb::ops::clean(config)?; - self.clean_manifests(&profile_dir)?; + Self::clean_manifests(&profile_dir)?; if self.all && profile_dir.exists() { trace!(?profile_dir, "Removing entire profile directory."); @@ -65,6 +65,7 @@ impl CleanArgs { #[cfg(test)] mod tests { use dojo_test_utils::compiler; + use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; use katana_runner::KatanaRunner; use sozo_ops::migration; @@ -84,6 +85,8 @@ mod tests { let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + // Plan the migration to generate some manifests other than base. config.tokio_handle().block_on(async { migration::migrate( @@ -94,6 +97,7 @@ mod tests { "dojo_examples", true, TxnConfig::default(), + dojo_metadata.skip_migration, ) .await .unwrap() diff --git a/bin/sozo/src/commands/dev.rs b/bin/sozo/src/commands/dev.rs index 2ff6eef64a..79d866b1a0 100644 --- a/bin/sozo/src/commands/dev.rs +++ b/bin/sozo/src/commands/dev.rs @@ -47,13 +47,13 @@ pub struct DevArgs { #[command(flatten)] pub account: AccountOptions, } - impl DevArgs { pub fn run(self, config: &Config) -> Result<()> { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; + let dojo_metadata = dojo_metadata_from_workspace(&ws); let env_metadata = if config.manifest_path().exists() { - dojo_metadata_from_workspace(&ws).env().cloned() + dojo_metadata.env().cloned() } else { trace!("Manifest path does not exist."); None @@ -97,6 +97,7 @@ impl DevArgs { &name, &context.ws, previous_manifest.clone(), + dojo_metadata.skip_migration.clone(), )) { Ok((manifest, address)) => { previous_manifest = Some(manifest); @@ -131,6 +132,7 @@ impl DevArgs { &name, &context.ws, previous_manifest.clone(), + dojo_metadata.skip_migration.clone(), )) { Ok((manifest, address)) => { previous_manifest = Some(manifest); @@ -222,12 +224,14 @@ fn build(context: &mut DevContext<'_>) -> Result<()> { Ok(()) } +// TODO: fix me async fn migrate( mut world_address: Option, account: &SingleOwnerAccount, name: &str, ws: &Workspace<'_>, previous_manifest: Option, + skip_migration: Option>, ) -> Result<(DeploymentManifest, Option)> where P: Provider + Sync + Send + 'static, @@ -243,9 +247,13 @@ where return Err(anyhow!("Build project using `sozo build` first")); } - let new_manifest = + let mut new_manifest = BaseManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(BASE_DIR))?; + if let Some(skip_manifests) = skip_migration { + new_manifest.remove_items(skip_manifests); + } + let diff = WorldDiff::compute(new_manifest.clone(), previous_manifest); let total_diffs = diff.count_diffs(); let config = ws.config(); diff --git a/bin/sozo/src/commands/migrate.rs b/bin/sozo/src/commands/migrate.rs index 1bf05338a8..6f6abe7404 100644 --- a/bin/sozo/src/commands/migrate.rs +++ b/bin/sozo/src/commands/migrate.rs @@ -58,6 +58,7 @@ impl MigrateArgs { pub fn run(self, config: &Config) -> Result<()> { trace!(args = ?self); let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; + let dojo_metadata = dojo_metadata_from_workspace(&ws); // This variant is tested before the match on `self.command` to avoid // having the need to spin up a Katana to generate the files. @@ -67,7 +68,7 @@ impl MigrateArgs { } let env_metadata = if config.manifest_path().exists() { - dojo_metadata_from_workspace(&ws).env().cloned() + dojo_metadata.env().cloned() } else { trace!("Manifest path does not exist."); None @@ -99,6 +100,7 @@ impl MigrateArgs { &name, true, TxnConfig::default(), + dojo_metadata.skip_migration, ) .await }), @@ -106,8 +108,17 @@ impl MigrateArgs { trace!(name, "Applying migration."); let txn_config: TxnConfig = transaction.into(); - migration::migrate(&ws, world_address, rpc_url, account, &name, false, txn_config) - .await + migration::migrate( + &ws, + world_address, + rpc_url, + account, + &name, + false, + txn_config, + dojo_metadata.skip_migration, + ) + .await }), _ => unreachable!("other case handled above."), } diff --git a/bin/sozo/tests/register_test.rs b/bin/sozo/tests/register_test.rs index 11053bd38f..7faf1ce474 100644 --- a/bin/sozo/tests/register_test.rs +++ b/bin/sozo/tests/register_test.rs @@ -3,6 +3,7 @@ mod utils; use camino::Utf8PathBuf; use dojo_test_utils::compiler; use dojo_test_utils::migration::prepare_migration; +use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; use katana_runner::KatanaRunner; use scarb::ops; @@ -20,11 +21,13 @@ async fn reregister_models() { let ws = ops::read_workspace(config.manifest_path(), &config) .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); + let dojo_metadata = dojo_metadata_from_workspace(&ws); - let base = config.manifest_path().parent().unwrap(); - let target_dir = format!("{}/target/dev", base); + let target_path = + ws.target_dir().path_existent().unwrap().join(ws.config().profile().to_string()); - let migration = prepare_migration(base.into(), target_dir.into()).unwrap(); + let migration = + prepare_migration(source_project_dir, target_path, dojo_metadata.skip_migration).unwrap(); let sequencer = KatanaRunner::new().expect("Failed to start runner."); diff --git a/crates/dojo-bindgen/Cargo.toml b/crates/dojo-bindgen/Cargo.toml index 1d9f376db1..8a97d8c2c2 100644 --- a/crates/dojo-bindgen/Cargo.toml +++ b/crates/dojo-bindgen/Cargo.toml @@ -22,3 +22,7 @@ thiserror.workspace = true cainome.workspace = true dojo-world = { path = "../dojo-world", features = [ "manifest" ] } + +[dev-dependencies] +dojo-test-utils = { path = "../dojo-test-utils", features = [ "build-examples" ] } +scarb = { workspace = true } diff --git a/crates/dojo-bindgen/src/lib.rs b/crates/dojo-bindgen/src/lib.rs index 5dfc2ff265..d92999ad14 100644 --- a/crates/dojo-bindgen/src/lib.rs +++ b/crates/dojo-bindgen/src/lib.rs @@ -73,13 +73,17 @@ pub struct PluginManager { impl PluginManager { /// Generates the bindings for all the given Plugin. - pub async fn generate(&self) -> BindgenResult<()> { + pub async fn generate(&self, skip_migration: Option>) -> BindgenResult<()> { if self.builtin_plugins.is_empty() && self.plugins.is_empty() { return Ok(()); } - let data = - gather_dojo_data(&self.manifest_path, &self.root_package_name, &self.profile_name)?; + let data = gather_dojo_data( + &self.manifest_path, + &self.root_package_name, + &self.profile_name, + skip_migration, + )?; for plugin in &self.builtin_plugins { // Get the plugin builder from the plugin enum. @@ -111,10 +115,15 @@ fn gather_dojo_data( manifest_path: &Utf8PathBuf, root_package_name: &str, profile_name: &str, + skip_migration: Option>, ) -> BindgenResult { let root_dir: Utf8PathBuf = manifest_path.parent().unwrap().into(); let base_manifest_dir: Utf8PathBuf = root_dir.join("manifests").join(profile_name).join("base"); - let base_manifest = BaseManifest::load_from_path(&base_manifest_dir)?; + let mut base_manifest = BaseManifest::load_from_path(&base_manifest_dir)?; + + if let Some(skip_manifests) = skip_migration { + base_manifest.remove_items(skip_manifests); + } let mut models = HashMap::new(); let mut contracts = HashMap::new(); @@ -244,6 +253,9 @@ fn model_name_from_fully_qualified_path(file_name: &str) -> Option { #[cfg(test)] mod tests { + use dojo_test_utils::compiler; + use dojo_world::metadata::dojo_metadata_from_workspace; + use super::*; #[test] @@ -254,14 +266,21 @@ mod tests { #[test] fn gather_data_ok() { - let data = gather_dojo_data( - &Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"), - "dojo_example", - "dev", - ) - .unwrap(); + let manifest_path = Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"); + + let config = compiler::copy_tmp_config( + &Utf8PathBuf::from("../../examples/spawn-and-move"), + &Utf8PathBuf::from("../dojo-core"), + ); + + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let data = + gather_dojo_data(&manifest_path, "dojo_example", "dev", dojo_metadata.skip_migration) + .unwrap(); - assert_eq!(data.models.len(), 6); + assert_eq!(data.models.len(), 7); assert_eq!(data.world.name, "dojo_example"); diff --git a/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs b/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs index 7ae5d5b2a6..498b032c86 100644 --- a/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs +++ b/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs @@ -237,7 +237,7 @@ function convertQueryToToriiClause(query: Query): Clause | undefined {{ constructor(contractAddress: string, account?: Account) {{ super(contractAddress, account); }} - + {} }} ", @@ -630,6 +630,8 @@ mod tests { use std::io::Read; use camino::Utf8PathBuf; + use dojo_test_utils::compiler; + use dojo_world::metadata::dojo_metadata_from_workspace; use super::*; use crate::gather_dojo_data; @@ -646,12 +648,17 @@ mod tests { let expected_output_without_header = expected_output.lines().skip(1).collect::>().join("\n"); - let data = gather_dojo_data( - &Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"), - "dojo_examples", - "dev", - ) - .unwrap(); + let manifest_path = Utf8PathBuf::from("src/test_data/spawn-and-move/Scarb.toml"); + let config = compiler::copy_tmp_config( + &Utf8PathBuf::from("../../examples/spawn-and-move"), + &Utf8PathBuf::from("../dojo-core"), + ); + + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + let data = + gather_dojo_data(&manifest_path, "dojo_examples", "dev", dojo_metadata.skip_migration) + .unwrap(); let actual_output = TypeScriptV2Plugin::generate_code_content(&data); let actual_output_without_header = diff --git a/crates/dojo-test-utils/src/migration.rs b/crates/dojo-test-utils/src/migration.rs index e8a576f341..9edfb3e969 100644 --- a/crates/dojo-test-utils/src/migration.rs +++ b/crates/dojo-test-utils/src/migration.rs @@ -10,6 +10,7 @@ use starknet::macros::felt; pub fn prepare_migration( manifest_dir: Utf8PathBuf, target_dir: Utf8PathBuf, + skip_migration: Option>, ) -> Result { // In testing, profile name is always dev. let profile_name = "dev"; @@ -19,6 +20,10 @@ pub fn prepare_migration( ) .unwrap(); + if let Some(skip_manifests) = skip_migration { + manifest.remove_items(skip_manifests); + } + let overlay_manifest = OverlayManifest::load_from_path( &manifest_dir.join(MANIFESTS_DIR).join(profile_name).join(OVERLAYS_DIR), ) diff --git a/crates/dojo-world/src/contracts/model_test.rs b/crates/dojo-world/src/contracts/model_test.rs index 178e9b6495..8aeeec1649 100644 --- a/crates/dojo-world/src/contracts/model_test.rs +++ b/crates/dojo-world/src/contracts/model_test.rs @@ -9,6 +9,7 @@ use starknet::macros::felt; use crate::contracts::model::ModelReader; use crate::contracts::world::test::deploy_world; use crate::contracts::world::WorldContractReader; +use crate::metadata::dojo_metadata_from_workspace; #[tokio::test(flavor = "multi_thread")] async fn test_model() { @@ -24,7 +25,12 @@ async fn test_model() { let manifest_dir = config.manifest_path().parent().unwrap(); let target_dir = manifest_dir.join("target").join("dev"); - let world_address = deploy_world(&runner, &manifest_dir.into(), &target_dir).await; + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let world_address = + deploy_world(&runner, &manifest_dir.into(), &target_dir, dojo_metadata.skip_migration) + .await; let world = WorldContractReader::new(world_address, provider); let position = world.model_reader("Position").await.unwrap(); diff --git a/crates/dojo-world/src/contracts/world_test.rs b/crates/dojo-world/src/contracts/world_test.rs index c011d573fb..21759c1ee2 100644 --- a/crates/dojo-world/src/contracts/world_test.rs +++ b/crates/dojo-world/src/contracts/world_test.rs @@ -8,6 +8,7 @@ use starknet::core::types::{BlockId, BlockTag, FieldElement}; use super::{WorldContract, WorldContractReader}; use crate::manifest::{BaseManifest, OverlayManifest, BASE_DIR, MANIFESTS_DIR, OVERLAYS_DIR}; +use crate::metadata::dojo_metadata_from_workspace; use crate::migration::strategy::prepare_for_migration; use crate::migration::world::WorldDiff; use crate::migration::{Declarable, Deployable, TxnConfig}; @@ -28,8 +29,16 @@ async fn test_world_contract_reader() { let provider = account.provider(); - let world_address = - deploy_world(&runner, &manifest_dir.to_path_buf(), &target_dir.to_path_buf()).await; + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let world_address = deploy_world( + &runner, + &manifest_dir.to_path_buf(), + &target_dir.to_path_buf(), + dojo_metadata.skip_migration, + ) + .await; let _world = WorldContractReader::new(world_address, provider); } @@ -38,6 +47,7 @@ pub async fn deploy_world( sequencer: &KatanaRunner, manifest_dir: &Utf8PathBuf, target_dir: &Utf8PathBuf, + skip_migration: Option>, ) -> FieldElement { // Dev profile is used by default for testing: let profile_name = "dev"; @@ -47,6 +57,10 @@ pub async fn deploy_world( ) .unwrap(); + if let Some(skip_manifests) = skip_migration { + manifest.remove_items(skip_manifests); + } + let overlay_manifest = OverlayManifest::load_from_path( &manifest_dir.join(MANIFESTS_DIR).join(profile_name).join(OVERLAYS_DIR), ) diff --git a/crates/dojo-world/src/manifest/manifest_test.rs b/crates/dojo-world/src/manifest/manifest_test.rs index a003fc0e23..b979b93675 100644 --- a/crates/dojo-world/src/manifest/manifest_test.rs +++ b/crates/dojo-world/src/manifest/manifest_test.rs @@ -6,6 +6,7 @@ use dojo_test_utils::compiler; use dojo_test_utils::rpc::MockJsonRpcTransport; use katana_runner::KatanaRunner; use serde_json::json; +use smol_str::SmolStr; use starknet::accounts::ConnectedAccount; use starknet::core::types::contract::AbiEntry; use starknet::core::types::{EmittedEvent, FieldElement}; @@ -21,6 +22,7 @@ use crate::manifest::{ parse_models_events, AbstractManifestError, DeploymentManifest, Manifest, OverlayClass, OverlayDojoModel, BASE_DIR, MANIFESTS_DIR, OVERLAYS_DIR, }; +use crate::metadata::dojo_metadata_from_workspace; use crate::migration::world::WorldDiff; #[tokio::test] @@ -381,17 +383,30 @@ fn fetch_remote_manifest() { let (temp_project_dir, config, _) = compiler::copy_build_project_temp(source_project, dojo_core_path, true); + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + let artifacts_path = temp_project_dir.join(format!("target/{profile_name}")); - let world_address = config - .tokio_handle() - .block_on(async { deploy_world(&runner, &temp_project_dir, &artifacts_path).await }); + let world_address = config.tokio_handle().block_on(async { + deploy_world( + &runner, + &temp_project_dir, + &artifacts_path, + dojo_metadata.skip_migration.clone(), + ) + .await + }); let mut local_manifest = BaseManifest::load_from_path( &temp_project_dir.join(MANIFESTS_DIR).join(profile_name).join(BASE_DIR), ) .unwrap(); + if let Some(skip_manifests) = dojo_metadata.skip_migration { + local_manifest.remove_items(skip_manifests); + } + let overlay_manifest = OverlayManifest::load_from_path( &temp_project_dir.join(MANIFESTS_DIR).join(profile_name).join(OVERLAYS_DIR), ) @@ -403,11 +418,11 @@ fn fetch_remote_manifest() { DeploymentManifest::load_from_remote(provider, world_address).await.unwrap() }); - assert_eq!(local_manifest.models.len(), 6); - assert_eq!(local_manifest.contracts.len(), 2); + assert_eq!(local_manifest.models.len(), 7); + assert_eq!(local_manifest.contracts.len(), 3); - assert_eq!(remote_manifest.models.len(), 6); - assert_eq!(remote_manifest.contracts.len(), 2); + assert_eq!(remote_manifest.models.len(), 7); + assert_eq!(remote_manifest.contracts.len(), 3); // compute diff from local and remote manifest @@ -641,3 +656,37 @@ fn overlay_merge_for_base_work_as_expected() { current.merge(other); assert_eq!(current, expected); } + +#[test] +fn base_manifest_remove_items_work_as_expected() { + let contracts = ["c1", "c2", "c3"]; + let models = ["m1", "m2", "m3"]; + + let world = Manifest { name: "world".into(), inner: Default::default() }; + let base = Manifest { name: "base".into(), inner: Default::default() }; + + let contracts = contracts + .iter() + .map(|c| Manifest { name: SmolStr::from(*c), inner: Default::default() }) + .collect(); + let models = models + .iter() + .map(|c| Manifest { name: SmolStr::from(*c), inner: Default::default() }) + .collect(); + + let mut base = BaseManifest { contracts, models, world, base }; + + base.remove_items(vec!["c1".to_string(), "c3".to_string(), "m2".to_string()]); + + assert_eq!(base.contracts.len(), 1); + assert_eq!( + base.contracts.iter().map(|c| c.name.clone().into()).collect::>(), + vec!["c2"] + ); + + assert_eq!(base.models.len(), 2); + assert_eq!( + base.models.iter().map(|c| c.name.clone().into()).collect::>(), + vec!["m1", "m3"] + ); +} diff --git a/crates/dojo-world/src/manifest/mod.rs b/crates/dojo-world/src/manifest/mod.rs index 5391761e49..d3906595ab 100644 --- a/crates/dojo-world/src/manifest/mod.rs +++ b/crates/dojo-world/src/manifest/mod.rs @@ -17,6 +17,7 @@ use starknet::macros::selector; use starknet::providers::{Provider, ProviderError}; use thiserror::Error; use toml; +use tracing::error; use crate::contracts::model::ModelError; use crate::contracts::world::WorldEvent; @@ -121,6 +122,12 @@ impl BaseManifest { Ok(Self { world, base, contracts, models }) } + /// Given a list of contract or model names, remove those from the manifest. + pub fn remove_items(&mut self, items: Vec) { + self.contracts.retain(|contract| !items.contains(&contract.name.to_string())); + self.models.retain(|model| !items.contains(&model.name.to_string())); + } + pub fn merge(&mut self, overlay: OverlayManifest) { let mut base_map = HashMap::new(); @@ -129,11 +136,15 @@ impl BaseManifest { } for contract in overlay.contracts { - base_map - .get_mut(&contract.name) - .expect("qed; overlay contract not found") - .inner - .merge(contract); + if let Some(manifest) = base_map.get_mut(&contract.name) { + manifest.inner.merge(contract); + } else { + error!( + "OverlayManifest configured for contract \"{}\", but contract is not present \ + in BaseManifest.", + contract.name + ); + } } if let Some(overlay_world) = overlay.world { diff --git a/crates/dojo-world/src/metadata.rs b/crates/dojo-world/src/metadata.rs index c432d09186..12f6cc837f 100644 --- a/crates/dojo-world/src/metadata.rs +++ b/crates/dojo-world/src/metadata.rs @@ -95,8 +95,11 @@ pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> DojoMetadata { let abis_dir = manifest_dir.join(ABIS_DIR).join(BASE_DIR); let project_metadata = ws.current_package().unwrap().manifest.metadata.dojo(); - let mut dojo_metadata = - DojoMetadata { env: project_metadata.env.clone(), ..Default::default() }; + let mut dojo_metadata = DojoMetadata { + env: project_metadata.env.clone(), + skip_migration: project_metadata.skip_migration.clone(), + ..Default::default() + }; let world_artifact = build_artifact_from_name(&sources_dir, &abis_dir, WORLD_CONTRACT_NAME); @@ -147,6 +150,7 @@ pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> DojoMetadata { pub struct ProjectMetadata { pub world: Option, pub env: Option, + pub skip_migration: Option>, } /// Metadata for a user defined resource (models, contracts). @@ -162,6 +166,7 @@ pub struct DojoMetadata { pub world: WorldMetadata, pub env: Option, pub resources_artifacts: HashMap, + pub skip_migration: Option>, } #[derive(Debug)] diff --git a/crates/dojo-world/src/metadata_test.rs b/crates/dojo-world/src/metadata_test.rs index 00da193bf8..adeb0df9a7 100644 --- a/crates/dojo-world/src/metadata_test.rs +++ b/crates/dojo-world/src/metadata_test.rs @@ -175,6 +175,7 @@ async fn get_full_dojo_metadata_from_workspace() { dbg!(&artifacts); for (abi_subdir, name) in artifacts { let resource = dojo_metadata.resources_artifacts.get(&name); + dbg!(&dojo_metadata.resources_artifacts); assert!(resource.is_some(), "bad resource metadata for {}", name); let resource = resource.unwrap(); @@ -230,6 +231,9 @@ fn get_artifacts_from_manifest(manifest_dir: &Utf8PathBuf) -> Vec<(String, Strin let name = name.replace("_others_", "::others::"); let name = name.replace("::others_", "::others::"); + + let name = name.replace("_mock_token_", "::mock_token::"); + let name = name.replace("::mock_token_", "::mock_token::"); artifacts.push(("models".to_string(), name)); } @@ -238,6 +242,7 @@ fn get_artifacts_from_manifest(manifest_dir: &Utf8PathBuf) -> Vec<(String, Strin let name = entry.path().file_stem().unwrap().to_string_lossy().to_string(); let name = name.replace("_actions_", "::actions::"); let name = name.replace("_others_", "::others::"); + let name = name.replace("_mock_token_", "::mock_token::"); artifacts.push(("contracts".to_string(), name)); } diff --git a/crates/sozo/ops/src/migration/mod.rs b/crates/sozo/ops/src/migration/mod.rs index d7d45d4c49..393ec72785 100644 --- a/crates/sozo/ops/src/migration/mod.rs +++ b/crates/sozo/ops/src/migration/mod.rs @@ -58,6 +58,7 @@ pub async fn migrate( name: &str, dry_run: bool, txn_config: TxnConfig, + skip_manifests: Option>, ) -> Result<()> where P: Provider + Sync + Send + 'static, @@ -77,15 +78,15 @@ where // Load local and remote World manifests. let (local_manifest, remote_manifest) = - utils::load_world_manifests(&profile_dir, &account, world_address, &ui).await.map_err( - |e| { + utils::load_world_manifests(&profile_dir, &account, world_address, &ui, skip_manifests) + .await + .map_err(|e| { ui.error(e.to_string()); anyhow!( "\n Use `sozo clean` to clean your project.\nThen, rebuild your project with \ `sozo build`.", ) - }, - )?; + })?; // Calculate diff between local and remote World manifests. ui.print_step(2, "🧰", "Evaluating Worlds diff..."); diff --git a/crates/sozo/ops/src/migration/utils.rs b/crates/sozo/ops/src/migration/utils.rs index d85ffb6df8..e8f6f50165 100644 --- a/crates/sozo/ops/src/migration/utils.rs +++ b/crates/sozo/ops/src/migration/utils.rs @@ -20,6 +20,7 @@ pub(super) async fn load_world_manifests( account: &SingleOwnerAccount, world_address: Option, ui: &Ui, + skip_migration: Option>, ) -> Result<(BaseManifest, Option)> where P: Provider + Sync + Send, @@ -30,6 +31,10 @@ where let mut local_manifest = BaseManifest::load_from_path(&profile_dir.join(BASE_DIR)) .map_err(|e| anyhow!("Fail to load local manifest file: {e}."))?; + if let Some(skip_manifests) = skip_migration { + local_manifest.remove_items(skip_manifests); + } + let overlay_path = profile_dir.join(OVERLAYS_DIR); if overlay_path.exists() { let overlay_manifest = OverlayManifest::load_from_path(&profile_dir.join(OVERLAYS_DIR)) diff --git a/crates/torii/core/src/sql_test.rs b/crates/torii/core/src/sql_test.rs index 360e0a988c..cceb20d657 100644 --- a/crates/torii/core/src/sql_test.rs +++ b/crates/torii/core/src/sql_test.rs @@ -4,6 +4,7 @@ use camino::Utf8PathBuf; use dojo_test_utils::compiler; use dojo_test_utils::migration::prepare_migration; use dojo_world::contracts::world::WorldContractReader; +use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; use dojo_world::utils::TransactionWaiter; use katana_runner::KatanaRunner; @@ -61,12 +62,16 @@ async fn test_load_from_remote() { let dojo_core_path = Utf8PathBuf::from("../../dojo-core"); let config = compiler::copy_tmp_config(&source_project_dir, &dojo_core_path); + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = dojo_metadata_from_workspace(&ws); let manifest_path = config.manifest_path(); let base_dir = manifest_path.parent().unwrap(); let target_dir = format!("{}/target/dev", base_dir); - let mut migration = prepare_migration(base_dir.into(), target_dir.into()).unwrap(); + let mut migration = + prepare_migration(base_dir.into(), target_dir.into(), dojo_metadata.skip_migration) + .unwrap(); migration.resolve_variable(migration.world_address().unwrap()).unwrap(); let sequencer = KatanaRunner::new().expect("Failed to start runner."); @@ -112,7 +117,7 @@ async fn test_load_from_remote() { let _block_timestamp = 1710754478_u64; let models = sqlx::query("SELECT * FROM models").fetch_all(&pool).await.unwrap(); - assert_eq!(models.len(), 6); + assert_eq!(models.len(), 7); let (id, name, packed_size, unpacked_size): (String, String, u8, u8) = sqlx::query_as( "SELECT id, name, packed_size, unpacked_size FROM models WHERE name = 'Position'", @@ -152,7 +157,7 @@ async fn test_load_from_remote() { // print all entities let entities = sqlx::query("SELECT * FROM entities").fetch_all(&pool).await.unwrap(); - assert_eq!(entities.len(), 1); + assert_eq!(entities.len(), 2); let (id, keys): (String, String) = sqlx::query_as( format!( diff --git a/crates/torii/graphql/src/tests/mod.rs b/crates/torii/graphql/src/tests/mod.rs index 86fcf37ad3..737cacc5ad 100644 --- a/crates/torii/graphql/src/tests/mod.rs +++ b/crates/torii/graphql/src/tests/mod.rs @@ -2,7 +2,8 @@ use std::str::FromStr; use anyhow::Result; use async_graphql::dynamic::Schema; -use dojo_test_utils::compiler::build_test_config; +use camino::Utf8PathBuf; +use dojo_test_utils::compiler::{self, build_test_config}; use dojo_test_utils::migration::prepare_migration; use dojo_test_utils::sequencer::{ get_default_test_starknet_config, SequencerConfig, TestSequencer, @@ -12,6 +13,7 @@ use dojo_types::schema::{Enum, EnumOption, Member, Struct, Ty}; use dojo_world::contracts::abi::model::Layout; use dojo_world::contracts::WorldContractReader; use dojo_world::manifest::DeploymentManifest; +use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; use dojo_world::utils::TransactionWaiter; use scarb::ops; @@ -277,9 +279,18 @@ pub async fn spinup_types_test() -> Result { let pool = SqlitePoolOptions::new().max_connections(5).connect_with(options).await.unwrap(); sqlx::migrate!("../migrations").run(&pool).await.unwrap(); - let base_path = "../types-test"; - let target_path = format!("{}/target/dev", base_path); - let migration = prepare_migration(base_path.into(), target_path.into()).unwrap(); + let source_project_dir = Utf8PathBuf::from("../types-test"); + let dojo_core_path = Utf8PathBuf::from("../../dojo-core"); + + let config = compiler::copy_tmp_config(&source_project_dir, &dojo_core_path); + + let ws = ops::read_workspace(config.manifest_path(), &config) + .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); + let migration = + prepare_migration(source_project_dir, target_path, dojo_metadata.skip_migration).unwrap(); let config = build_test_config("../types-test/Scarb.toml").unwrap(); let db = Sql::new(pool.clone(), migration.world_address().unwrap()).await.unwrap(); @@ -294,7 +305,7 @@ pub async fn spinup_types_test() -> Result { let ws = ops::read_workspace(config.manifest_path(), &config) .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); - execute_strategy(&ws, &migration, &account, TxnConfig::default()).await.unwrap(); + execute_strategy(&ws, &migration, &account, TxnConfig::init_wait()).await.unwrap(); let manifest = DeploymentManifest::load_from_remote(&provider, migration.world_address().unwrap()) diff --git a/crates/torii/grpc/Cargo.toml b/crates/torii/grpc/Cargo.toml index 48fd1a8c20..3673a790a2 100644 --- a/crates/torii/grpc/Cargo.toml +++ b/crates/torii/grpc/Cargo.toml @@ -31,6 +31,7 @@ tower.workspace = true tracing.workspace = true [dev-dependencies] +camino.workspace = true dojo-test-utils.workspace = true dojo-world = { path = "../../dojo-world", features = [ "contracts" ] } scarb.workspace = true diff --git a/crates/torii/grpc/src/server/tests/entities_test.rs b/crates/torii/grpc/src/server/tests/entities_test.rs index 4776659558..786c1ffd1a 100644 --- a/crates/torii/grpc/src/server/tests/entities_test.rs +++ b/crates/torii/grpc/src/server/tests/entities_test.rs @@ -1,12 +1,14 @@ use std::str::FromStr; use std::sync::Arc; -use dojo_test_utils::compiler::build_test_config; +use camino::Utf8PathBuf; +use dojo_test_utils::compiler::{self, build_test_config}; use dojo_test_utils::migration::prepare_migration; use dojo_test_utils::sequencer::{ get_default_test_starknet_config, SequencerConfig, TestSequencer, }; use dojo_world::contracts::WorldContractReader; +use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; use dojo_world::utils::TransactionWaiter; use scarb::ops; @@ -34,10 +36,20 @@ async fn test_entities_queries() { SqliteConnectOptions::from_str("sqlite::memory:").unwrap().create_if_missing(true); let pool = SqlitePoolOptions::new().max_connections(5).connect_with(options).await.unwrap(); sqlx::migrate!("../migrations").run(&pool).await.unwrap(); - let base_path = "../../../examples/spawn-and-move"; - let target_path = format!("{}/target/dev", base_path); - let mut migration = prepare_migration(base_path.into(), target_path.into()).unwrap(); + let source_project_dir = Utf8PathBuf::from("../../../examples/spawn-and-move"); + let dojo_core_path = Utf8PathBuf::from("../../dojo-core"); + + let config = compiler::copy_tmp_config(&source_project_dir, &dojo_core_path); + + let ws = ops::read_workspace(config.manifest_path(), &config) + .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); + let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); + + let mut migration = + prepare_migration(source_project_dir, target_path, dojo_metadata.skip_migration).unwrap(); migration.resolve_variable(migration.world_address().unwrap()).unwrap(); dbg!(&migration); diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index e8b10f51c5..5dd277ffa0 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -15,6 +15,8 @@ dojo = { path = "../../crates/dojo-core" } [[target.dojo]] build-external-contracts = [ ] +# `dev` profile + [tool.dojo.world] description = "example world" name = "example" @@ -26,3 +28,27 @@ rpc_url = "http://localhost:5050/" account_address = "0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03" private_key = "0x1800000000300000180000000000030000000000003006001800006600" world_address = "0x07efebb0c2d4cc285d48a97a7174def3be7fdd6b7bd29cca758fa2e17e03ef30" + +# `release` profile +# +# for now configurations in `tool` are not merged recursively so to override +# `skip_migration` we need to redefine the whole `tool.dojo` table +[profile.release] + +[profile.release.tool.dojo.world] +description = "example world" +name = "example" + +[profile.release.tool.dojo.env] +rpc_url = "http://localhost:5050/" + +# Default account for katana with seed = 0 +account_address = "0x6162896d1d7ab204c7ccac6dd5f8e9e7c25ecd5ae4fcb4ad32e57786bb46e03" +private_key = "0x1800000000300000180000000000030000000000003006001800006600" +world_address = "0x07efebb0c2d4cc285d48a97a7174def3be7fdd6b7bd29cca758fa2e17e03ef30" + +[profile.release.tool.dojo] +skip_migration = [ + "dojo_examples::mock_token::mock_token", + "dojo_examples::models::mock_token", +] diff --git a/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_mock_token_mock_token.json b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_mock_token_mock_token.json new file mode 100644 index 0000000000..f4bde33e6d --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_mock_token_mock_token.json @@ -0,0 +1,133 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::mock_token::mock_token::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::mock_token::mock_token::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::mock_token::mock_token::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/dev/abis/base/models/dojo_examples_models_mock_token.json b/examples/spawn-and-move/manifests/dev/abis/base/models/dojo_examples_models_mock_token.json new file mode 100644 index 0000000000..b2c1c340fa --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/abis/base/models/dojo_examples_models_mock_token.json @@ -0,0 +1,363 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "mock_tokenImpl", + "interface_name": "dojo_examples::models::Imock_token" + }, + { + "type": "struct", + "name": "dojo_examples::models::MockToken", + "members": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u128" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imock_token", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::MockToken" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::mock_token::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_mock_token_mock_token.json b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_mock_token_mock_token.json new file mode 100644 index 0000000000..f4bde33e6d --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_mock_token_mock_token.json @@ -0,0 +1,133 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::mock_token::mock_token::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::mock_token::mock_token::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::mock_token::mock_token::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/dev/abis/deployments/models/dojo_examples_models_mock_token.json b/examples/spawn-and-move/manifests/dev/abis/deployments/models/dojo_examples_models_mock_token.json new file mode 100644 index 0000000000..b2c1c340fa --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/abis/deployments/models/dojo_examples_models_mock_token.json @@ -0,0 +1,363 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "mock_tokenImpl", + "interface_name": "dojo_examples::models::Imock_token" + }, + { + "type": "struct", + "name": "dojo_examples::models::MockToken", + "members": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u128" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imock_token", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::MockToken" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::mock_token::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_mock_token_mock_token.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_mock_token_mock_token.toml new file mode 100644 index 0000000000..572af4068e --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_mock_token_mock_token.toml @@ -0,0 +1,10 @@ +kind = "DojoContract" +class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +original_class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +base_class_hash = "0x0" +abi = "manifests/dev/abis/base/contracts/dojo_examples_mock_token_mock_token.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +name = "dojo_examples::mock_token::mock_token" diff --git a/examples/spawn-and-move/manifests/dev/base/models/dojo_examples_models_mock_token.toml b/examples/spawn-and-move/manifests/dev/base/models/dojo_examples_models_mock_token.toml new file mode 100644 index 0000000000..1bf036168c --- /dev/null +++ b/examples/spawn-and-move/manifests/dev/base/models/dojo_examples_models_mock_token.toml @@ -0,0 +1,15 @@ +kind = "DojoModel" +class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +original_class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +abi = "manifests/dev/abis/base/models/dojo_examples_models_mock_token.json" +name = "dojo_examples::models::mock_token" + +[[members]] +name = "account" +type = "ContractAddress" +key = true + +[[members]] +name = "amount" +type = "u128" +key = false diff --git a/examples/spawn-and-move/manifests/dev/manifest.json b/examples/spawn-and-move/manifests/dev/manifest.json index 0b6a6af2fb..9f2e854a95 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.json +++ b/examples/spawn-and-move/manifests/dev/manifest.json @@ -1333,6 +1333,151 @@ "init_calldata": [], "name": "dojo_examples::actions::actions" }, + { + "kind": "DojoContract", + "address": "0x75961b2027c52948ecebfd347aa427436ea308d41997fa9b3c98380f7011d53", + "class_hash": "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2", + "original_class_hash": "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2", + "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", + "abi": [ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::mock_token::mock_token::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::mock_token::mock_token::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::mock_token::mock_token::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [], + "computed": [], + "init_calldata": [], + "name": "dojo_examples::mock_token::mock_token" + }, { "kind": "DojoContract", "address": "0x3f51cd82daaf5907d2fd082ae3f45ae2ef96ab61677f46abc16e0a54d3392d1", @@ -2303,6 +2448,387 @@ ], "name": "dojo_examples::models::message" }, + { + "kind": "DojoModel", + "members": [ + { + "name": "account", + "type": "ContractAddress", + "key": true + }, + { + "name": "amount", + "type": "u128", + "key": false + } + ], + "class_hash": "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d", + "original_class_hash": "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "mock_tokenImpl", + "interface_name": "dojo_examples::models::Imock_token" + }, + { + "type": "struct", + "name": "dojo_examples::models::MockToken", + "members": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u128" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imock_token", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::MockToken" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::mock_token::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::models::mock_token" + }, { "kind": "DojoModel", "members": [ diff --git a/examples/spawn-and-move/manifests/dev/manifest.toml b/examples/spawn-and-move/manifests/dev/manifest.toml index 601c02ab1b..ec501b9733 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/manifest.toml @@ -35,6 +35,19 @@ computed = [] init_calldata = [] name = "dojo_examples::actions::actions" +[[contracts]] +kind = "DojoContract" +address = "0x75961b2027c52948ecebfd347aa427436ea308d41997fa9b3c98380f7011d53" +class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +original_class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +abi = "manifests/dev/abis/deployments/contracts/dojo_examples_mock_token_mock_token.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +name = "dojo_examples::mock_token::mock_token" + [[contracts]] kind = "DojoContract" address = "0x3f51cd82daaf5907d2fd082ae3f45ae2ef96ab61677f46abc16e0a54d3392d1" @@ -96,6 +109,23 @@ name = "salt" type = "felt252" key = true +[[models]] +kind = "DojoModel" +class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +original_class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +abi = "manifests/dev/abis/deployments/models/dojo_examples_models_mock_token.json" +name = "dojo_examples::models::mock_token" + +[[models.members]] +name = "account" +type = "ContractAddress" +key = true + +[[models.members]] +name = "amount" +type = "u128" +key = false + [[models]] kind = "DojoModel" class_hash = "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8" diff --git a/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_actions_actions.json new file mode 100644 index 0000000000..21aed968a7 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_actions_actions.json @@ -0,0 +1,290 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsComputedImpl", + "interface_name": "dojo_examples::actions::IActionsComputed" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActionsComputed", + "items": [ + { + "type": "function", + "name": "tile_terrain", + "inputs": [ + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "quadrant", + "inputs": [ + { + "name": "pos", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsImpl", + "interface_name": "dojo_examples::actions::IActions" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActions", + "items": [ + { + "type": "function", + "name": "spawn", + "inputs": [], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "move", + "inputs": [ + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_player_config", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::actions::actions::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_mock_token_mock_token.json b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_mock_token_mock_token.json new file mode 100644 index 0000000000..f4bde33e6d --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_mock_token_mock_token.json @@ -0,0 +1,133 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::mock_token::mock_token::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::mock_token::mock_token::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::mock_token::mock_token::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_others_others.json b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_others_others.json new file mode 100644 index 0000000000..36d8c3ef78 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/contracts/dojo_examples_others_others.json @@ -0,0 +1,146 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::others::others::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::others::others::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [ + { + "name": "actions_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "actions_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/dojo_world_world.json b/examples/spawn-and-move/manifests/release/abis/base/dojo_world_world.json new file mode 100644 index 0000000000..c1a2447839 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/dojo_world_world.json @@ -0,0 +1,996 @@ +[ + { + "type": "impl", + "name": "World", + "interface_name": "dojo::world::IWorld" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo::resource_metadata::ResourceMetadata", + "members": [ + { + "name": "resource_id", + "type": "core::felt252" + }, + { + "name": "metadata_uri", + "type": "core::byte_array::ByteArray" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorld", + "items": [ + { + "type": "function", + "name": "metadata", + "inputs": [ + { + "name": "resource_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_metadata", + "inputs": [ + { + "name": "metadata", + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "model", + "inputs": [ + { + "name": "selector", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "(core::starknet::class_hash::ClassHash, core::starknet::contract_address::ContractAddress)" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "register_model", + "inputs": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "deploy_contract", + "inputs": [ + { + "name": "salt", + "type": "core::felt252" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "init_calldata", + "type": "core::array::Span::" + } + ], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "upgrade_contract", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "uuid", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u32" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "emit", + "inputs": [ + { + "name": "keys", + "type": "core::array::Array::" + }, + { + "name": "values", + "type": "core::array::Span::" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [ + { + "type": "core::array::Span::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "values", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "delete_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "base", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "is_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "is_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableWorld", + "interface_name": "dojo::world::IUpgradeableWorld" + }, + { + "type": "interface", + "name": "dojo::world::IUpgradeableWorld", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableState", + "interface_name": "dojo::interfaces::IUpgradeableState" + }, + { + "type": "struct", + "name": "dojo::interfaces::StorageUpdate", + "members": [ + { + "name": "key", + "type": "core::felt252" + }, + { + "name": "value", + "type": "core::felt252" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::interfaces::ProgramOutput", + "members": [ + { + "name": "prev_state_root", + "type": "core::felt252" + }, + { + "name": "new_state_root", + "type": "core::felt252" + }, + { + "name": "block_number", + "type": "core::felt252" + }, + { + "name": "block_hash", + "type": "core::felt252" + }, + { + "name": "config_hash", + "type": "core::felt252" + }, + { + "name": "world_da_hash", + "type": "core::felt252" + }, + { + "name": "message_to_starknet_segment", + "type": "core::array::Span::" + }, + { + "name": "message_to_appchain_segment", + "type": "core::array::Span::" + } + ] + }, + { + "type": "interface", + "name": "dojo::interfaces::IUpgradeableState", + "items": [ + { + "type": "function", + "name": "upgrade_state", + "inputs": [ + { + "name": "new_state", + "type": "core::array::Span::" + }, + { + "name": "program_output", + "type": "dojo::interfaces::ProgramOutput" + }, + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "ConfigImpl", + "interface_name": "dojo::config::interface::IConfig" + }, + { + "type": "interface", + "name": "dojo::config::interface::IConfig", + "items": [ + { + "type": "function", + "name": "set_differ_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "set_merger_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_differ_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "get_merger_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_facts_registry", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_facts_registry", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "constructor", + "name": "constructor", + "inputs": [ + { + "name": "contract_base", + "type": "core::starknet::class_hash::ClassHash" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldSpawned", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "creator", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractDeployed", + "kind": "struct", + "members": [ + { + "name": "salt", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::MetadataUpdate", + "kind": "struct", + "members": [ + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "uri", + "type": "core::byte_array::ByteArray", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ModelRegistered", + "kind": "struct", + "members": [ + { + "name": "name", + "type": "core::byte_array::ByteArray", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "prev_class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "prev_address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreSetRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + }, + { + "name": "values", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WriterUpdated", + "kind": "struct", + "members": [ + { + "name": "model", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::OwnerUpdated", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::Event", + "kind": "enum", + "variants": [ + { + "name": "DifferProgramHashUpdate", + "type": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "nested" + }, + { + "name": "MergerProgramHashUpdate", + "type": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "nested" + }, + { + "name": "FactsRegistryUpdate", + "type": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StateUpdated", + "kind": "struct", + "members": [ + { + "name": "da_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::Event", + "kind": "enum", + "variants": [ + { + "name": "WorldSpawned", + "type": "dojo::world::world::WorldSpawned", + "kind": "nested" + }, + { + "name": "ContractDeployed", + "type": "dojo::world::world::ContractDeployed", + "kind": "nested" + }, + { + "name": "ContractUpgraded", + "type": "dojo::world::world::ContractUpgraded", + "kind": "nested" + }, + { + "name": "WorldUpgraded", + "type": "dojo::world::world::WorldUpgraded", + "kind": "nested" + }, + { + "name": "MetadataUpdate", + "type": "dojo::world::world::MetadataUpdate", + "kind": "nested" + }, + { + "name": "ModelRegistered", + "type": "dojo::world::world::ModelRegistered", + "kind": "nested" + }, + { + "name": "StoreSetRecord", + "type": "dojo::world::world::StoreSetRecord", + "kind": "nested" + }, + { + "name": "StoreDelRecord", + "type": "dojo::world::world::StoreDelRecord", + "kind": "nested" + }, + { + "name": "WriterUpdated", + "type": "dojo::world::world::WriterUpdated", + "kind": "nested" + }, + { + "name": "OwnerUpdated", + "type": "dojo::world::world::OwnerUpdated", + "kind": "nested" + }, + { + "name": "ConfigEvent", + "type": "dojo::config::component::Config::Event", + "kind": "nested" + }, + { + "name": "StateUpdated", + "type": "dojo::world::world::StateUpdated", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_actions_actions_moved.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_actions_actions_moved.json new file mode 100644 index 0000000000..89abdcfec5 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_actions_actions_moved.json @@ -0,0 +1,389 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movedImpl", + "interface_name": "dojo_examples::actions::actions::Imoved" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::actions::actions::Moved", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::Imoved", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::actions::actions::Moved" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::moved::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_message.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_message.json new file mode 100644 index 0000000000..ec760c99fb --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_message.json @@ -0,0 +1,371 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "messageImpl", + "interface_name": "dojo_examples::models::Imessage" + }, + { + "type": "struct", + "name": "dojo_examples::models::Message", + "members": [ + { + "name": "identity", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "channel", + "type": "core::felt252" + }, + { + "name": "message", + "type": "core::byte_array::ByteArray" + }, + { + "name": "salt", + "type": "core::felt252" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imessage", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Message" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::message::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_mock_token.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_mock_token.json new file mode 100644 index 0000000000..b2c1c340fa --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_mock_token.json @@ -0,0 +1,363 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "mock_tokenImpl", + "interface_name": "dojo_examples::models::Imock_token" + }, + { + "type": "struct", + "name": "dojo_examples::models::MockToken", + "members": [ + { + "name": "account", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "amount", + "type": "core::integer::u128" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imock_token", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::MockToken" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::mock_token::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_moves.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_moves.json new file mode 100644 index 0000000000..ee2cf17b26 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_moves.json @@ -0,0 +1,393 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movesImpl", + "interface_name": "dojo_examples::models::Imoves" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Moves", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "remaining", + "type": "core::integer::u8" + }, + { + "name": "last_direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imoves", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Moves" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::moves::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_player_config.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_player_config.json new file mode 100644 index 0000000000..8c33ebabc4 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_player_config.json @@ -0,0 +1,385 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "player_configImpl", + "interface_name": "dojo_examples::models::Iplayer_config" + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerItem", + "members": [ + { + "name": "item_id", + "type": "core::integer::u32" + }, + { + "name": "quantity", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerConfig", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "name", + "type": "core::byte_array::ByteArray" + }, + { + "name": "items", + "type": "core::array::Array::" + }, + { + "name": "favorite_item", + "type": "core::option::Option::" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iplayer_config", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::PlayerConfig" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::player_config::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_position.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_position.json new file mode 100644 index 0000000000..bceec42587 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_models_position.json @@ -0,0 +1,377 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "positionImpl", + "interface_name": "dojo_examples::models::Iposition" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iposition", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::position::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_others_others_contract_initialized.json b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_others_others_contract_initialized.json new file mode 100644 index 0000000000..1dbbd313d8 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/base/models/dojo_examples_others_others_contract_initialized.json @@ -0,0 +1,367 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "contract_initializedImpl", + "interface_name": "dojo_examples::others::others::Icontract_initialized" + }, + { + "type": "struct", + "name": "dojo_examples::others::others::ContractInitialized", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "contract_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::others::others::Icontract_initialized", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::others::others::ContractInitialized" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::contract_initialized::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_actions_actions.json new file mode 100644 index 0000000000..21aed968a7 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_actions_actions.json @@ -0,0 +1,290 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsComputedImpl", + "interface_name": "dojo_examples::actions::IActionsComputed" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActionsComputed", + "items": [ + { + "type": "function", + "name": "tile_terrain", + "inputs": [ + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "quadrant", + "inputs": [ + { + "name": "pos", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsImpl", + "interface_name": "dojo_examples::actions::IActions" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActions", + "items": [ + { + "type": "function", + "name": "spawn", + "inputs": [], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "move", + "inputs": [ + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_player_config", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::actions::actions::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_others_others.json b/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_others_others.json new file mode 100644 index 0000000000..36d8c3ef78 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/contracts/dojo_examples_others_others.json @@ -0,0 +1,146 @@ +[ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::others::others::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::others::others::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [ + { + "name": "actions_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "actions_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/dojo_world_world.json b/examples/spawn-and-move/manifests/release/abis/deployments/dojo_world_world.json new file mode 100644 index 0000000000..c1a2447839 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/dojo_world_world.json @@ -0,0 +1,996 @@ +[ + { + "type": "impl", + "name": "World", + "interface_name": "dojo::world::IWorld" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo::resource_metadata::ResourceMetadata", + "members": [ + { + "name": "resource_id", + "type": "core::felt252" + }, + { + "name": "metadata_uri", + "type": "core::byte_array::ByteArray" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorld", + "items": [ + { + "type": "function", + "name": "metadata", + "inputs": [ + { + "name": "resource_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_metadata", + "inputs": [ + { + "name": "metadata", + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "model", + "inputs": [ + { + "name": "selector", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "(core::starknet::class_hash::ClassHash, core::starknet::contract_address::ContractAddress)" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "register_model", + "inputs": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "deploy_contract", + "inputs": [ + { + "name": "salt", + "type": "core::felt252" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "init_calldata", + "type": "core::array::Span::" + } + ], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "upgrade_contract", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "uuid", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u32" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "emit", + "inputs": [ + { + "name": "keys", + "type": "core::array::Array::" + }, + { + "name": "values", + "type": "core::array::Span::" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [ + { + "type": "core::array::Span::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "values", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "delete_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "base", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "is_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "is_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableWorld", + "interface_name": "dojo::world::IUpgradeableWorld" + }, + { + "type": "interface", + "name": "dojo::world::IUpgradeableWorld", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableState", + "interface_name": "dojo::interfaces::IUpgradeableState" + }, + { + "type": "struct", + "name": "dojo::interfaces::StorageUpdate", + "members": [ + { + "name": "key", + "type": "core::felt252" + }, + { + "name": "value", + "type": "core::felt252" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::interfaces::ProgramOutput", + "members": [ + { + "name": "prev_state_root", + "type": "core::felt252" + }, + { + "name": "new_state_root", + "type": "core::felt252" + }, + { + "name": "block_number", + "type": "core::felt252" + }, + { + "name": "block_hash", + "type": "core::felt252" + }, + { + "name": "config_hash", + "type": "core::felt252" + }, + { + "name": "world_da_hash", + "type": "core::felt252" + }, + { + "name": "message_to_starknet_segment", + "type": "core::array::Span::" + }, + { + "name": "message_to_appchain_segment", + "type": "core::array::Span::" + } + ] + }, + { + "type": "interface", + "name": "dojo::interfaces::IUpgradeableState", + "items": [ + { + "type": "function", + "name": "upgrade_state", + "inputs": [ + { + "name": "new_state", + "type": "core::array::Span::" + }, + { + "name": "program_output", + "type": "dojo::interfaces::ProgramOutput" + }, + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "ConfigImpl", + "interface_name": "dojo::config::interface::IConfig" + }, + { + "type": "interface", + "name": "dojo::config::interface::IConfig", + "items": [ + { + "type": "function", + "name": "set_differ_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "set_merger_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_differ_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "get_merger_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_facts_registry", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_facts_registry", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "constructor", + "name": "constructor", + "inputs": [ + { + "name": "contract_base", + "type": "core::starknet::class_hash::ClassHash" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldSpawned", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "creator", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractDeployed", + "kind": "struct", + "members": [ + { + "name": "salt", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::MetadataUpdate", + "kind": "struct", + "members": [ + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "uri", + "type": "core::byte_array::ByteArray", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ModelRegistered", + "kind": "struct", + "members": [ + { + "name": "name", + "type": "core::byte_array::ByteArray", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "prev_class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "prev_address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreSetRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + }, + { + "name": "values", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WriterUpdated", + "kind": "struct", + "members": [ + { + "name": "model", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::OwnerUpdated", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::Event", + "kind": "enum", + "variants": [ + { + "name": "DifferProgramHashUpdate", + "type": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "nested" + }, + { + "name": "MergerProgramHashUpdate", + "type": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "nested" + }, + { + "name": "FactsRegistryUpdate", + "type": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StateUpdated", + "kind": "struct", + "members": [ + { + "name": "da_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::Event", + "kind": "enum", + "variants": [ + { + "name": "WorldSpawned", + "type": "dojo::world::world::WorldSpawned", + "kind": "nested" + }, + { + "name": "ContractDeployed", + "type": "dojo::world::world::ContractDeployed", + "kind": "nested" + }, + { + "name": "ContractUpgraded", + "type": "dojo::world::world::ContractUpgraded", + "kind": "nested" + }, + { + "name": "WorldUpgraded", + "type": "dojo::world::world::WorldUpgraded", + "kind": "nested" + }, + { + "name": "MetadataUpdate", + "type": "dojo::world::world::MetadataUpdate", + "kind": "nested" + }, + { + "name": "ModelRegistered", + "type": "dojo::world::world::ModelRegistered", + "kind": "nested" + }, + { + "name": "StoreSetRecord", + "type": "dojo::world::world::StoreSetRecord", + "kind": "nested" + }, + { + "name": "StoreDelRecord", + "type": "dojo::world::world::StoreDelRecord", + "kind": "nested" + }, + { + "name": "WriterUpdated", + "type": "dojo::world::world::WriterUpdated", + "kind": "nested" + }, + { + "name": "OwnerUpdated", + "type": "dojo::world::world::OwnerUpdated", + "kind": "nested" + }, + { + "name": "ConfigEvent", + "type": "dojo::config::component::Config::Event", + "kind": "nested" + }, + { + "name": "StateUpdated", + "type": "dojo::world::world::StateUpdated", + "kind": "nested" + } + ] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_actions_actions_moved.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_actions_actions_moved.json new file mode 100644 index 0000000000..89abdcfec5 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_actions_actions_moved.json @@ -0,0 +1,389 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movedImpl", + "interface_name": "dojo_examples::actions::actions::Imoved" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::actions::actions::Moved", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::Imoved", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::actions::actions::Moved" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::moved::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_emote_message.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_emote_message.json new file mode 100644 index 0000000000..9c63d0fc5d --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_emote_message.json @@ -0,0 +1,389 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "emote_messageImpl", + "interface_name": "dojo_examples::models::Iemote_message" + }, + { + "type": "enum", + "name": "dojo_examples::models::Emote", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Happy", + "type": "()" + }, + { + "name": "Sad", + "type": "()" + }, + { + "name": "Angry", + "type": "()" + }, + { + "name": "Love", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::EmoteMessage", + "members": [ + { + "name": "identity", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "emote", + "type": "dojo_examples::models::Emote" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iemote_message", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::EmoteMessage" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::emote_message::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_message.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_message.json new file mode 100644 index 0000000000..ec760c99fb --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_message.json @@ -0,0 +1,371 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "messageImpl", + "interface_name": "dojo_examples::models::Imessage" + }, + { + "type": "struct", + "name": "dojo_examples::models::Message", + "members": [ + { + "name": "identity", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "channel", + "type": "core::felt252" + }, + { + "name": "message", + "type": "core::byte_array::ByteArray" + }, + { + "name": "salt", + "type": "core::felt252" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imessage", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Message" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::message::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_moves.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_moves.json new file mode 100644 index 0000000000..ee2cf17b26 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_moves.json @@ -0,0 +1,393 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movesImpl", + "interface_name": "dojo_examples::models::Imoves" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Moves", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "remaining", + "type": "core::integer::u8" + }, + { + "name": "last_direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imoves", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Moves" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::moves::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_player_config.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_player_config.json new file mode 100644 index 0000000000..8c33ebabc4 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_player_config.json @@ -0,0 +1,385 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "player_configImpl", + "interface_name": "dojo_examples::models::Iplayer_config" + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerItem", + "members": [ + { + "name": "item_id", + "type": "core::integer::u32" + }, + { + "name": "quantity", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerConfig", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "name", + "type": "core::byte_array::ByteArray" + }, + { + "name": "items", + "type": "core::array::Array::" + }, + { + "name": "favorite_item", + "type": "core::option::Option::" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iplayer_config", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::PlayerConfig" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::player_config::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_position.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_position.json new file mode 100644 index 0000000000..bceec42587 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_models_position.json @@ -0,0 +1,377 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "positionImpl", + "interface_name": "dojo_examples::models::Iposition" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iposition", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::position::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_others_others_contract_initialized.json b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_others_others_contract_initialized.json new file mode 100644 index 0000000000..1dbbd313d8 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/abis/deployments/models/dojo_examples_others_others_contract_initialized.json @@ -0,0 +1,367 @@ +[ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "contract_initializedImpl", + "interface_name": "dojo_examples::others::others::Icontract_initialized" + }, + { + "type": "struct", + "name": "dojo_examples::others::others::ContractInitialized", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "contract_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::others::others::Icontract_initialized", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::others::others::ContractInitialized" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::contract_initialized::Event", + "kind": "enum", + "variants": [] + } +] \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_actions_actions.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_actions_actions.toml new file mode 100644 index 0000000000..bf0f86489b --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_actions_actions.toml @@ -0,0 +1,10 @@ +kind = "DojoContract" +class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +original_class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +base_class_hash = "0x0" +abi = "manifests/release/abis/base/contracts/dojo_examples_actions_actions.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +name = "dojo_examples::actions::actions" diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_mock_token_mock_token.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_mock_token_mock_token.toml new file mode 100644 index 0000000000..65fbfcc8ad --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_mock_token_mock_token.toml @@ -0,0 +1,10 @@ +kind = "DojoContract" +class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +original_class_hash = "0x5c32bc974f96f82ded691bb95bf26b2783f874fffb50fe84a331acb75ecf5b2" +base_class_hash = "0x0" +abi = "manifests/release/abis/base/contracts/dojo_examples_mock_token_mock_token.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +name = "dojo_examples::mock_token::mock_token" diff --git a/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_others_others.toml b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_others_others.toml new file mode 100644 index 0000000000..66cb83c9d6 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/contracts/dojo_examples_others_others.toml @@ -0,0 +1,10 @@ +kind = "DojoContract" +class_hash = "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a" +original_class_hash = "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a" +base_class_hash = "0x0" +abi = "manifests/release/abis/base/contracts/dojo_examples_others_others.json" +reads = [] +writes = [] +computed = [] +init_calldata = [] +name = "dojo_examples::others::others" diff --git a/examples/spawn-and-move/manifests/release/base/dojo_base_base.toml b/examples/spawn-and-move/manifests/release/base/dojo_base_base.toml new file mode 100644 index 0000000000..6c4b5de67e --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/dojo_base_base.toml @@ -0,0 +1,4 @@ +kind = "Class" +class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +original_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +name = "dojo::base::base" diff --git a/examples/spawn-and-move/manifests/release/base/dojo_world_world.toml b/examples/spawn-and-move/manifests/release/base/dojo_world_world.toml new file mode 100644 index 0000000000..e9badcfe4c --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/dojo_world_world.toml @@ -0,0 +1,5 @@ +kind = "Class" +class_hash = "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9" +original_class_hash = "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9" +abi = "manifests/release/abis/base/dojo_world_world.json" +name = "dojo::world::world" diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_actions_actions_moved.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_actions_actions_moved.toml new file mode 100644 index 0000000000..74c1e890a1 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_actions_actions_moved.toml @@ -0,0 +1,15 @@ +kind = "DojoModel" +class_hash = "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c" +original_class_hash = "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c" +abi = "manifests/release/abis/base/models/dojo_examples_actions_actions_moved.json" +name = "dojo_examples::actions::actions::moved" + +[[members]] +name = "player" +type = "ContractAddress" +key = true + +[[members]] +name = "direction" +type = "Direction" +key = false diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_message.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_message.toml new file mode 100644 index 0000000000..fdc87b27cb --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_message.toml @@ -0,0 +1,25 @@ +kind = "DojoModel" +class_hash = "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5" +original_class_hash = "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5" +abi = "manifests/release/abis/base/models/dojo_examples_models_message.json" +name = "dojo_examples::models::message" + +[[members]] +name = "identity" +type = "ContractAddress" +key = true + +[[members]] +name = "channel" +type = "felt252" +key = true + +[[members]] +name = "message" +type = "ByteArray" +key = false + +[[members]] +name = "salt" +type = "felt252" +key = true diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_mock_token.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_mock_token.toml new file mode 100644 index 0000000000..3d0147bc11 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_mock_token.toml @@ -0,0 +1,15 @@ +kind = "DojoModel" +class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +original_class_hash = "0x6a21c56878ba470ac7a51f336ca6a59781de38e1810d2d20866ab2b52138a6d" +abi = "manifests/release/abis/base/models/dojo_examples_models_mock_token.json" +name = "dojo_examples::models::mock_token" + +[[members]] +name = "account" +type = "ContractAddress" +key = true + +[[members]] +name = "amount" +type = "u128" +key = false diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_moves.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_moves.toml new file mode 100644 index 0000000000..8954550f5e --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_moves.toml @@ -0,0 +1,20 @@ +kind = "DojoModel" +class_hash = "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8" +original_class_hash = "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8" +abi = "manifests/release/abis/base/models/dojo_examples_models_moves.json" +name = "dojo_examples::models::moves" + +[[members]] +name = "player" +type = "ContractAddress" +key = true + +[[members]] +name = "remaining" +type = "u8" +key = false + +[[members]] +name = "last_direction" +type = "Direction" +key = false diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_player_config.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_player_config.toml new file mode 100644 index 0000000000..bbeae83193 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_player_config.toml @@ -0,0 +1,25 @@ +kind = "DojoModel" +class_hash = "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55" +original_class_hash = "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55" +abi = "manifests/release/abis/base/models/dojo_examples_models_player_config.json" +name = "dojo_examples::models::player_config" + +[[members]] +name = "player" +type = "ContractAddress" +key = true + +[[members]] +name = "name" +type = "ByteArray" +key = false + +[[members]] +name = "items" +type = "Array" +key = false + +[[members]] +name = "favorite_item" +type = "Option" +key = false diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_position.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_position.toml new file mode 100644 index 0000000000..562adaba78 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_models_position.toml @@ -0,0 +1,15 @@ +kind = "DojoModel" +class_hash = "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff" +original_class_hash = "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff" +abi = "manifests/release/abis/base/models/dojo_examples_models_position.json" +name = "dojo_examples::models::position" + +[[members]] +name = "player" +type = "ContractAddress" +key = true + +[[members]] +name = "vec" +type = "Vec2" +key = false diff --git a/examples/spawn-and-move/manifests/release/base/models/dojo_examples_others_others_contract_initialized.toml b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_others_others_contract_initialized.toml new file mode 100644 index 0000000000..51efb699ba --- /dev/null +++ b/examples/spawn-and-move/manifests/release/base/models/dojo_examples_others_others_contract_initialized.toml @@ -0,0 +1,20 @@ +kind = "DojoModel" +class_hash = "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c" +original_class_hash = "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c" +abi = "manifests/release/abis/base/models/dojo_examples_others_others_contract_initialized.json" +name = "dojo_examples::others::others::contract_initialized" + +[[members]] +name = "contract_address" +type = "ContractAddress" +key = true + +[[members]] +name = "contract_class" +type = "ClassHash" +key = false + +[[members]] +name = "value" +type = "u8" +key = false diff --git a/examples/spawn-and-move/manifests/release/manifest.json b/examples/spawn-and-move/manifests/release/manifest.json new file mode 100644 index 0000000000..8ae464adc9 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/manifest.json @@ -0,0 +1,3910 @@ +{ + "world": { + "kind": "WorldContract", + "class_hash": "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9", + "original_class_hash": "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9", + "abi": [ + { + "type": "impl", + "name": "World", + "interface_name": "dojo::world::IWorld" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo::resource_metadata::ResourceMetadata", + "members": [ + { + "name": "resource_id", + "type": "core::felt252" + }, + { + "name": "metadata_uri", + "type": "core::byte_array::ByteArray" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorld", + "items": [ + { + "type": "function", + "name": "metadata", + "inputs": [ + { + "name": "resource_id", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_metadata", + "inputs": [ + { + "name": "metadata", + "type": "dojo::resource_metadata::ResourceMetadata" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "model", + "inputs": [ + { + "name": "selector", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "(core::starknet::class_hash::ClassHash, core::starknet::contract_address::ContractAddress)" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "register_model", + "inputs": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "deploy_contract", + "inputs": [ + { + "name": "salt", + "type": "core::felt252" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "init_calldata", + "type": "core::array::Span::" + } + ], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "upgrade_contract", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "uuid", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u32" + } + ], + "state_mutability": "external" + }, + { + "type": "function", + "name": "emit", + "inputs": [ + { + "name": "keys", + "type": "core::array::Array::" + }, + { + "name": "values", + "type": "core::array::Span::" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [ + { + "type": "core::array::Span::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "values", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "delete_entity", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "keys", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "base", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::class_hash::ClassHash" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "is_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_owner", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "resource", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "is_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [ + { + "type": "core::bool" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "grant_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "revoke_writer", + "inputs": [ + { + "name": "model", + "type": "core::felt252" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableWorld", + "interface_name": "dojo::world::IUpgradeableWorld" + }, + { + "type": "interface", + "name": "dojo::world::IUpgradeableWorld", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "UpgradeableState", + "interface_name": "dojo::interfaces::IUpgradeableState" + }, + { + "type": "struct", + "name": "dojo::interfaces::StorageUpdate", + "members": [ + { + "name": "key", + "type": "core::felt252" + }, + { + "name": "value", + "type": "core::felt252" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::interfaces::ProgramOutput", + "members": [ + { + "name": "prev_state_root", + "type": "core::felt252" + }, + { + "name": "new_state_root", + "type": "core::felt252" + }, + { + "name": "block_number", + "type": "core::felt252" + }, + { + "name": "block_hash", + "type": "core::felt252" + }, + { + "name": "config_hash", + "type": "core::felt252" + }, + { + "name": "world_da_hash", + "type": "core::felt252" + }, + { + "name": "message_to_starknet_segment", + "type": "core::array::Span::" + }, + { + "name": "message_to_appchain_segment", + "type": "core::array::Span::" + } + ] + }, + { + "type": "interface", + "name": "dojo::interfaces::IUpgradeableState", + "items": [ + { + "type": "function", + "name": "upgrade_state", + "inputs": [ + { + "name": "new_state", + "type": "core::array::Span::" + }, + { + "name": "program_output", + "type": "dojo::interfaces::ProgramOutput" + }, + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "impl", + "name": "ConfigImpl", + "interface_name": "dojo::config::interface::IConfig" + }, + { + "type": "interface", + "name": "dojo::config::interface::IConfig", + "items": [ + { + "type": "function", + "name": "set_differ_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "set_merger_program_hash", + "inputs": [ + { + "name": "program_hash", + "type": "core::felt252" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_differ_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "get_merger_program_hash", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_facts_registry", + "inputs": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "get_facts_registry", + "inputs": [], + "outputs": [ + { + "type": "core::starknet::contract_address::ContractAddress" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "constructor", + "name": "constructor", + "inputs": [ + { + "name": "contract_base", + "type": "core::starknet::class_hash::ClassHash" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldSpawned", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "creator", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractDeployed", + "kind": "struct", + "members": [ + { + "name": "salt", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ContractUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WorldUpgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::MetadataUpdate", + "kind": "struct", + "members": [ + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "uri", + "type": "core::byte_array::ByteArray", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::ModelRegistered", + "kind": "struct", + "members": [ + { + "name": "name", + "type": "core::byte_array::ByteArray", + "kind": "data" + }, + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "prev_class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + }, + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "prev_address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreSetRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + }, + { + "name": "values", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StoreDelRecord", + "kind": "struct", + "members": [ + { + "name": "table", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "keys", + "type": "core::array::Span::", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::WriterUpdated", + "kind": "struct", + "members": [ + { + "name": "model", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "contract", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::OwnerUpdated", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + }, + { + "name": "resource", + "type": "core::felt252", + "kind": "data" + }, + { + "name": "value", + "type": "core::bool", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "struct", + "members": [ + { + "name": "program_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "struct", + "members": [ + { + "name": "address", + "type": "core::starknet::contract_address::ContractAddress", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::config::component::Config::Event", + "kind": "enum", + "variants": [ + { + "name": "DifferProgramHashUpdate", + "type": "dojo::config::component::Config::DifferProgramHashUpdate", + "kind": "nested" + }, + { + "name": "MergerProgramHashUpdate", + "type": "dojo::config::component::Config::MergerProgramHashUpdate", + "kind": "nested" + }, + { + "name": "FactsRegistryUpdate", + "type": "dojo::config::component::Config::FactsRegistryUpdate", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::StateUpdated", + "kind": "struct", + "members": [ + { + "name": "da_hash", + "type": "core::felt252", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::world::world::Event", + "kind": "enum", + "variants": [ + { + "name": "WorldSpawned", + "type": "dojo::world::world::WorldSpawned", + "kind": "nested" + }, + { + "name": "ContractDeployed", + "type": "dojo::world::world::ContractDeployed", + "kind": "nested" + }, + { + "name": "ContractUpgraded", + "type": "dojo::world::world::ContractUpgraded", + "kind": "nested" + }, + { + "name": "WorldUpgraded", + "type": "dojo::world::world::WorldUpgraded", + "kind": "nested" + }, + { + "name": "MetadataUpdate", + "type": "dojo::world::world::MetadataUpdate", + "kind": "nested" + }, + { + "name": "ModelRegistered", + "type": "dojo::world::world::ModelRegistered", + "kind": "nested" + }, + { + "name": "StoreSetRecord", + "type": "dojo::world::world::StoreSetRecord", + "kind": "nested" + }, + { + "name": "StoreDelRecord", + "type": "dojo::world::world::StoreDelRecord", + "kind": "nested" + }, + { + "name": "WriterUpdated", + "type": "dojo::world::world::WriterUpdated", + "kind": "nested" + }, + { + "name": "OwnerUpdated", + "type": "dojo::world::world::OwnerUpdated", + "kind": "nested" + }, + { + "name": "ConfigEvent", + "type": "dojo::config::component::Config::Event", + "kind": "nested" + }, + { + "name": "StateUpdated", + "type": "dojo::world::world::StateUpdated", + "kind": "nested" + } + ] + } + ], + "address": "0x7efebb0c2d4cc285d48a97a7174def3be7fdd6b7bd29cca758fa2e17e03ef30", + "transaction_hash": "0x60316eb232789f4d8352c6afdc36b76d33362d72b43bf78183b43f196779a9d", + "block_number": 3, + "seed": "dojo_examples", + "metadata": { + "profile_name": "release", + "rpc_url": "http://localhost:5050/" + }, + "name": "dojo::world::world" + }, + "base": { + "kind": "Class", + "class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", + "original_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", + "abi": null, + "name": "dojo::base::base" + }, + "contracts": [ + { + "kind": "DojoContract", + "address": "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af", + "class_hash": "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767", + "original_class_hash": "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767", + "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", + "abi": [ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsComputedImpl", + "interface_name": "dojo_examples::actions::IActionsComputed" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActionsComputed", + "items": [ + { + "type": "function", + "name": "tile_terrain", + "inputs": [ + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "quadrant", + "inputs": [ + { + "name": "pos", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "ActionsImpl", + "interface_name": "dojo_examples::actions::IActions" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::IActions", + "items": [ + { + "type": "function", + "name": "spawn", + "inputs": [], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "move", + "inputs": [ + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ], + "outputs": [], + "state_mutability": "view" + }, + { + "type": "function", + "name": "set_player_config", + "inputs": [ + { + "name": "name", + "type": "core::byte_array::ByteArray" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::actions::actions::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [ + "Moves", + "Position" + ], + "computed": [], + "init_calldata": [], + "name": "dojo_examples::actions::actions" + }, + { + "kind": "DojoContract", + "address": "0x3f51cd82daaf5907d2fd082ae3f45ae2ef96ab61677f46abc16e0a54d3392d1", + "class_hash": "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a", + "original_class_hash": "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a", + "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", + "abi": [ + { + "type": "impl", + "name": "DojoResourceProviderImpl", + "interface_name": "dojo::world::IDojoResourceProvider" + }, + { + "type": "interface", + "name": "dojo::world::IDojoResourceProvider", + "items": [ + { + "type": "function", + "name": "dojo_resource", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "WorldProviderImpl", + "interface_name": "dojo::world::IWorldProvider" + }, + { + "type": "struct", + "name": "dojo::world::IWorldDispatcher", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + } + ] + }, + { + "type": "interface", + "name": "dojo::world::IWorldProvider", + "items": [ + { + "type": "function", + "name": "world", + "inputs": [], + "outputs": [ + { + "type": "dojo::world::IWorldDispatcher" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "IDojoInitImpl", + "interface_name": "dojo_examples::others::others::IDojoInit" + }, + { + "type": "interface", + "name": "dojo_examples::others::others::IDojoInit", + "items": [ + { + "type": "function", + "name": "dojo_init", + "inputs": [ + { + "name": "actions_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "actions_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "UpgradableImpl", + "interface_name": "dojo::components::upgradeable::IUpgradeable" + }, + { + "type": "interface", + "name": "dojo::components::upgradeable::IUpgradeable", + "items": [ + { + "type": "function", + "name": "upgrade", + "inputs": [ + { + "name": "new_class_hash", + "type": "core::starknet::class_hash::ClassHash" + } + ], + "outputs": [], + "state_mutability": "external" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "struct", + "members": [ + { + "name": "class_hash", + "type": "core::starknet::class_hash::ClassHash", + "kind": "data" + } + ] + }, + { + "type": "event", + "name": "dojo::components::upgradeable::upgradeable::Event", + "kind": "enum", + "variants": [ + { + "name": "Upgraded", + "type": "dojo::components::upgradeable::upgradeable::Upgraded", + "kind": "nested" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::Event", + "kind": "enum", + "variants": [ + { + "name": "UpgradeableEvent", + "type": "dojo::components::upgradeable::upgradeable::Event", + "kind": "nested" + } + ] + } + ], + "reads": [], + "writes": [], + "computed": [], + "init_calldata": [ + "$class_hash:dojo_examples::actions::actions", + "$contract_address:dojo_examples::actions::actions", + "10" + ], + "name": "dojo_examples::others::others" + } + ], + "models": [ + { + "kind": "DojoModel", + "members": [ + { + "name": "player", + "type": "ContractAddress", + "key": true + }, + { + "name": "direction", + "type": "Direction", + "key": false + } + ], + "class_hash": "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c", + "original_class_hash": "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movedImpl", + "interface_name": "dojo_examples::actions::actions::Imoved" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::actions::actions::Moved", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::actions::actions::Imoved", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::actions::actions::Moved" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::actions::actions::moved::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::actions::actions::moved" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "identity", + "type": "ContractAddress", + "key": true + }, + { + "name": "channel", + "type": "felt252", + "key": true + }, + { + "name": "message", + "type": "ByteArray", + "key": false + }, + { + "name": "salt", + "type": "felt252", + "key": true + } + ], + "class_hash": "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5", + "original_class_hash": "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "messageImpl", + "interface_name": "dojo_examples::models::Imessage" + }, + { + "type": "struct", + "name": "dojo_examples::models::Message", + "members": [ + { + "name": "identity", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "channel", + "type": "core::felt252" + }, + { + "name": "message", + "type": "core::byte_array::ByteArray" + }, + { + "name": "salt", + "type": "core::felt252" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imessage", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Message" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::message::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::models::message" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "player", + "type": "ContractAddress", + "key": true + }, + { + "name": "remaining", + "type": "u8", + "key": false + }, + { + "name": "last_direction", + "type": "Direction", + "key": false + } + ], + "class_hash": "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8", + "original_class_hash": "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "movesImpl", + "interface_name": "dojo_examples::models::Imoves" + }, + { + "type": "enum", + "name": "dojo_examples::models::Direction", + "variants": [ + { + "name": "None", + "type": "()" + }, + { + "name": "Left", + "type": "()" + }, + { + "name": "Right", + "type": "()" + }, + { + "name": "Up", + "type": "()" + }, + { + "name": "Down", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Moves", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "remaining", + "type": "core::integer::u8" + }, + { + "name": "last_direction", + "type": "dojo_examples::models::Direction" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Imoves", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Moves" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::moves::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::models::moves" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "player", + "type": "ContractAddress", + "key": true + }, + { + "name": "name", + "type": "ByteArray", + "key": false + }, + { + "name": "items", + "type": "Array", + "key": false + }, + { + "name": "favorite_item", + "type": "Option", + "key": false + } + ], + "class_hash": "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55", + "original_class_hash": "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "player_configImpl", + "interface_name": "dojo_examples::models::Iplayer_config" + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerItem", + "members": [ + { + "name": "item_id", + "type": "core::integer::u32" + }, + { + "name": "quantity", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::PlayerConfig", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "name", + "type": "core::byte_array::ByteArray" + }, + { + "name": "items", + "type": "core::array::Array::" + }, + { + "name": "favorite_item", + "type": "core::option::Option::" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iplayer_config", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::PlayerConfig" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::player_config::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::models::player_config" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "player", + "type": "ContractAddress", + "key": true + }, + { + "name": "vec", + "type": "Vec2", + "key": false + } + ], + "class_hash": "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff", + "original_class_hash": "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "positionImpl", + "interface_name": "dojo_examples::models::Iposition" + }, + { + "type": "struct", + "name": "dojo_examples::models::Vec2", + "members": [ + { + "name": "x", + "type": "core::integer::u32" + }, + { + "name": "y", + "type": "core::integer::u32" + } + ] + }, + { + "type": "struct", + "name": "dojo_examples::models::Position", + "members": [ + { + "name": "player", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "vec", + "type": "dojo_examples::models::Vec2" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::models::Iposition", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::models::Position" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::models::position::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::models::position" + }, + { + "kind": "DojoModel", + "members": [ + { + "name": "contract_address", + "type": "ContractAddress", + "key": true + }, + { + "name": "contract_class", + "type": "ClassHash", + "key": false + }, + { + "name": "value", + "type": "u8", + "key": false + } + ], + "class_hash": "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c", + "original_class_hash": "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c", + "abi": [ + { + "type": "impl", + "name": "DojoModelImpl", + "interface_name": "dojo::model::IModel" + }, + { + "type": "struct", + "name": "core::byte_array::ByteArray", + "members": [ + { + "name": "data", + "type": "core::array::Array::" + }, + { + "name": "pending_word", + "type": "core::felt252" + }, + { + "name": "pending_word_len", + "type": "core::integer::u32" + } + ] + }, + { + "type": "enum", + "name": "core::option::Option::", + "variants": [ + { + "name": "Some", + "type": "core::integer::u32" + }, + { + "name": "None", + "type": "()" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::FieldLayout", + "members": [ + { + "name": "selector", + "type": "core::felt252" + }, + { + "name": "layout", + "type": "dojo::database::introspect::Layout" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Layout", + "variants": [ + { + "name": "Fixed", + "type": "core::array::Span::" + }, + { + "name": "Struct", + "type": "core::array::Span::" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + }, + { + "name": "Enum", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Member", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "ty", + "type": "dojo::database::introspect::Ty" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Struct", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "dojo::database::introspect::Enum", + "members": [ + { + "name": "name", + "type": "core::felt252" + }, + { + "name": "attrs", + "type": "core::array::Span::" + }, + { + "name": "children", + "type": "core::array::Span::<(core::felt252, dojo::database::introspect::Ty)>" + } + ] + }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "dojo::database::introspect::Ty", + "variants": [ + { + "name": "Primitive", + "type": "core::felt252" + }, + { + "name": "Struct", + "type": "dojo::database::introspect::Struct" + }, + { + "name": "Enum", + "type": "dojo::database::introspect::Enum" + }, + { + "name": "Tuple", + "type": "core::array::Span::" + }, + { + "name": "Array", + "type": "core::array::Span::" + }, + { + "name": "ByteArray", + "type": "()" + } + ] + }, + { + "type": "interface", + "name": "dojo::model::IModel", + "items": [ + { + "type": "function", + "name": "selector", + "inputs": [], + "outputs": [ + { + "type": "core::felt252" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "name", + "inputs": [], + "outputs": [ + { + "type": "core::byte_array::ByteArray" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "version", + "inputs": [], + "outputs": [ + { + "type": "core::integer::u8" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "unpacked_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "packed_size", + "inputs": [], + "outputs": [ + { + "type": "core::option::Option::" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "layout", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Layout" + } + ], + "state_mutability": "view" + }, + { + "type": "function", + "name": "schema", + "inputs": [], + "outputs": [ + { + "type": "dojo::database::introspect::Ty" + } + ], + "state_mutability": "view" + } + ] + }, + { + "type": "impl", + "name": "contract_initializedImpl", + "interface_name": "dojo_examples::others::others::Icontract_initialized" + }, + { + "type": "struct", + "name": "dojo_examples::others::others::ContractInitialized", + "members": [ + { + "name": "contract_address", + "type": "core::starknet::contract_address::ContractAddress" + }, + { + "name": "contract_class", + "type": "core::starknet::class_hash::ClassHash" + }, + { + "name": "value", + "type": "core::integer::u8" + } + ] + }, + { + "type": "interface", + "name": "dojo_examples::others::others::Icontract_initialized", + "items": [ + { + "type": "function", + "name": "ensure_abi", + "inputs": [ + { + "name": "model", + "type": "dojo_examples::others::others::ContractInitialized" + } + ], + "outputs": [], + "state_mutability": "view" + } + ] + }, + { + "type": "event", + "name": "dojo_examples::others::others::contract_initialized::Event", + "kind": "enum", + "variants": [] + } + ], + "name": "dojo_examples::others::others::contract_initialized" + } + ] +} \ No newline at end of file diff --git a/examples/spawn-and-move/manifests/release/manifest.toml b/examples/spawn-and-move/manifests/release/manifest.toml new file mode 100644 index 0000000000..71ebf9944e --- /dev/null +++ b/examples/spawn-and-move/manifests/release/manifest.toml @@ -0,0 +1,185 @@ +[world] +kind = "WorldContract" +class_hash = "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9" +original_class_hash = "0x3f63cecdc4964acafb921ba2934c6507d1b3c344edb64c2762cf08053169ab9" +abi = "manifests/release/abis/deployments/dojo_world_world.json" +address = "0x7efebb0c2d4cc285d48a97a7174def3be7fdd6b7bd29cca758fa2e17e03ef30" +transaction_hash = "0x60316eb232789f4d8352c6afdc36b76d33362d72b43bf78183b43f196779a9d" +block_number = 3 +seed = "dojo_examples" +name = "dojo::world::world" + +[world.metadata] +profile_name = "release" +rpc_url = "http://localhost:5050/" + +[base] +kind = "Class" +class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +original_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +name = "dojo::base::base" + +[[contracts]] +kind = "DojoContract" +address = "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af" +class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +original_class_hash = "0x6d905953360cf18e3393d128c6ced40b38fc83b033412c8541fd4aba59d2767" +base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +abi = "manifests/release/abis/deployments/contracts/dojo_examples_actions_actions.json" +reads = [] +writes = [ + "Moves", + "Position", +] +computed = [] +init_calldata = [] +name = "dojo_examples::actions::actions" + +[[contracts]] +kind = "DojoContract" +address = "0x3f51cd82daaf5907d2fd082ae3f45ae2ef96ab61677f46abc16e0a54d3392d1" +class_hash = "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a" +original_class_hash = "0x3ee016157303a7ce35a9fecdb5b8519159df620c5780527d61443636aaa3c3a" +base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" +abi = "manifests/release/abis/deployments/contracts/dojo_examples_others_others.json" +reads = [] +writes = [] +computed = [] +init_calldata = [ + "$class_hash:dojo_examples::actions::actions", + "$contract_address:dojo_examples::actions::actions", + "10", +] +name = "dojo_examples::others::others" + +[[models]] +kind = "DojoModel" +class_hash = "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c" +original_class_hash = "0x4ef89963afe500337aaf757ad52394ea8e311077a825b3de5a5f32d3457997c" +abi = "manifests/release/abis/deployments/models/dojo_examples_actions_actions_moved.json" +name = "dojo_examples::actions::actions::moved" + +[[models.members]] +name = "player" +type = "ContractAddress" +key = true + +[[models.members]] +name = "direction" +type = "Direction" +key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5" +original_class_hash = "0x33bdb1a470ea0ee7d77faa3c75151934b3b129c0bad7333ec6c2dad1b98ec5" +abi = "manifests/release/abis/deployments/models/dojo_examples_models_message.json" +name = "dojo_examples::models::message" + +[[models.members]] +name = "identity" +type = "ContractAddress" +key = true + +[[models.members]] +name = "channel" +type = "felt252" +key = true + +[[models.members]] +name = "message" +type = "ByteArray" +key = false + +[[models.members]] +name = "salt" +type = "felt252" +key = true + +[[models]] +kind = "DojoModel" +class_hash = "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8" +original_class_hash = "0x456d85286b34249fffa0a13d1ac490cc1f5b02eb1a1c92d820c59d6b0f2eaa8" +abi = "manifests/release/abis/deployments/models/dojo_examples_models_moves.json" +name = "dojo_examples::models::moves" + +[[models.members]] +name = "player" +type = "ContractAddress" +key = true + +[[models.members]] +name = "remaining" +type = "u8" +key = false + +[[models.members]] +name = "last_direction" +type = "Direction" +key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55" +original_class_hash = "0x584d016a91d077c86ff1c014e0c4d735946d1084dd0d4c0a80cee6d04629e55" +abi = "manifests/release/abis/deployments/models/dojo_examples_models_player_config.json" +name = "dojo_examples::models::player_config" + +[[models.members]] +name = "player" +type = "ContractAddress" +key = true + +[[models.members]] +name = "name" +type = "ByteArray" +key = false + +[[models.members]] +name = "items" +type = "Array" +key = false + +[[models.members]] +name = "favorite_item" +type = "Option" +key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff" +original_class_hash = "0x27942375b09862291ece780c573e8c625df4ba41fd7524e0658ca75fff014ff" +abi = "manifests/release/abis/deployments/models/dojo_examples_models_position.json" +name = "dojo_examples::models::position" + +[[models.members]] +name = "player" +type = "ContractAddress" +key = true + +[[models.members]] +name = "vec" +type = "Vec2" +key = false + +[[models]] +kind = "DojoModel" +class_hash = "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c" +original_class_hash = "0x4b29afc6db744bd87f7276869620348557c11b984e9f3fcb27c4d55efb0ab6c" +abi = "manifests/release/abis/deployments/models/dojo_examples_others_others_contract_initialized.json" +name = "dojo_examples::others::others::contract_initialized" + +[[models.members]] +name = "contract_address" +type = "ContractAddress" +key = true + +[[models.members]] +name = "contract_class" +type = "ClassHash" +key = false + +[[models.members]] +name = "value" +type = "u8" +key = false diff --git a/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_actions_actions.toml b/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_actions_actions.toml new file mode 100644 index 0000000000..188130a013 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_actions_actions.toml @@ -0,0 +1,4 @@ +init_calldata = [ ] +name = "dojo_examples::actions::actions" +reads = [ ] +writes = [ "Moves", "Position" ] diff --git a/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_others_others.toml b/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_others_others.toml new file mode 100644 index 0000000000..82545bca81 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/contracts/dojo_examples_others_others.toml @@ -0,0 +1,8 @@ +init_calldata = [ + "$class_hash:dojo_examples::actions::actions", + "$contract_address:dojo_examples::actions::actions", + "10", +] +name = "dojo_examples::others::others" +reads = [ ] +writes = [ ] diff --git a/examples/spawn-and-move/manifests/release/overlays/dojo_base_base.toml b/examples/spawn-and-move/manifests/release/overlays/dojo_base_base.toml new file mode 100644 index 0000000000..f706470d45 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/dojo_base_base.toml @@ -0,0 +1 @@ +name = "dojo::base::base" diff --git a/examples/spawn-and-move/manifests/release/overlays/dojo_world_world.toml b/examples/spawn-and-move/manifests/release/overlays/dojo_world_world.toml new file mode 100644 index 0000000000..a3e686e3ef --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/dojo_world_world.toml @@ -0,0 +1 @@ +name = "dojo::world::world" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_actions_actions_moved.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_actions_actions_moved.toml new file mode 100644 index 0000000000..4958a7a15c --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_actions_actions_moved.toml @@ -0,0 +1 @@ +name = "dojo_examples::actions::actions::moved" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_message.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_message.toml new file mode 100644 index 0000000000..5d9412cae2 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_message.toml @@ -0,0 +1 @@ +name = "dojo_examples::models::message" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_mock_token.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_mock_token.toml new file mode 100644 index 0000000000..a5ba5684a6 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_mock_token.toml @@ -0,0 +1 @@ +name = "dojo_examples::models::mock_token" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_moves.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_moves.toml new file mode 100644 index 0000000000..dc8784e746 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_moves.toml @@ -0,0 +1 @@ +name = "dojo_examples::models::moves" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_player_config.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_player_config.toml new file mode 100644 index 0000000000..6af8240b36 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_player_config.toml @@ -0,0 +1 @@ +name = "dojo_examples::models::player_config" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_position.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_position.toml new file mode 100644 index 0000000000..df38e71c32 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_models_position.toml @@ -0,0 +1 @@ +name = "dojo_examples::models::position" diff --git a/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_others_others_contract_initialized.toml b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_others_others_contract_initialized.toml new file mode 100644 index 0000000000..f8f3053fe5 --- /dev/null +++ b/examples/spawn-and-move/manifests/release/overlays/models/dojo_examples_others_others_contract_initialized.toml @@ -0,0 +1 @@ +name = "dojo_examples::others::others::contract_initialized" diff --git a/examples/spawn-and-move/src/lib.cairo b/examples/spawn-and-move/src/lib.cairo index 44309e5fca..b1273839ec 100644 --- a/examples/spawn-and-move/src/lib.cairo +++ b/examples/spawn-and-move/src/lib.cairo @@ -2,3 +2,4 @@ mod actions; mod models; mod utils; mod others; +mod mock_token; diff --git a/examples/spawn-and-move/src/mock_token.cairo b/examples/spawn-and-move/src/mock_token.cairo new file mode 100644 index 0000000000..75b4c00e16 --- /dev/null +++ b/examples/spawn-and-move/src/mock_token.cairo @@ -0,0 +1,11 @@ +#[dojo::contract] +mod mock_token { + use dojo_examples::models::{MockToken}; + use starknet::{ContractAddress, get_caller_address}; + + fn dojo_init(world: @IWorldDispatcher) { + let account: ContractAddress = get_caller_address(); + + set!(world, MockToken { account: account, amount: 1000 }); + } +} diff --git a/examples/spawn-and-move/src/models.cairo b/examples/spawn-and-move/src/models.cairo index a0b733e28c..85cfdf1711 100644 --- a/examples/spawn-and-move/src/models.cairo +++ b/examples/spawn-and-move/src/models.cairo @@ -42,6 +42,14 @@ struct Moves { last_direction: Direction } +#[derive(Copy, Drop, Serde)] +#[dojo::model] +struct MockToken { + #[key] + account: ContractAddress, + amount: u128, +} + #[derive(Copy, Drop, Serde, IntrospectPacked)] struct Vec2 { x: u32, From d6561159fbd438dd73dfa93e215ebbb7d205edc0 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Thu, 13 Jun 2024 21:25:09 -0400 Subject: [PATCH 09/32] Prepare release: v0.7.0 (#2055) --- Cargo.lock | 90 ++++++++++---------- Cargo.toml | 2 +- crates/dojo-core/Scarb.lock | 2 +- crates/dojo-core/Scarb.toml | 2 +- crates/katana/runner/runner-macro/Cargo.toml | 2 +- crates/torii/types-test/Scarb.lock | 2 +- crates/torii/types-test/Scarb.toml | 2 +- examples/spawn-and-move/Scarb.lock | 2 +- examples/spawn-and-move/Scarb.toml | 2 +- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 877b081274..3e5c038dd6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,7 +1338,7 @@ dependencies = [ [[package]] name = "benches" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "clap", @@ -3776,7 +3776,7 @@ dependencies = [ [[package]] name = "common" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "reqwest 0.12.4", @@ -4577,7 +4577,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dojo-bindgen" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "async-trait", "cainome", @@ -4595,15 +4595,15 @@ dependencies = [ [[package]] name = "dojo-core" -version = "0.7.0-alpha.5" +version = "0.7.0" [[package]] name = "dojo-examples-spawn-and-move" -version = "0.7.0-alpha.5" +version = "0.7.0" [[package]] name = "dojo-lang" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "cairo-lang-compiler 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -4654,7 +4654,7 @@ dependencies = [ [[package]] name = "dojo-language-server" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "cairo-lang-language-server", "clap", @@ -4663,7 +4663,7 @@ dependencies = [ [[package]] name = "dojo-metrics" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "hyper 0.14.28", @@ -4681,7 +4681,7 @@ dependencies = [ [[package]] name = "dojo-test-utils" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_fs", @@ -4715,7 +4715,7 @@ dependencies = [ [[package]] name = "dojo-types" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "cainome", "crypto-bigint", @@ -4731,7 +4731,7 @@ dependencies = [ [[package]] name = "dojo-world" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_fs", @@ -4770,7 +4770,7 @@ dependencies = [ [[package]] name = "dojo-world-abigen" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", "cairo-lang-starknet-classes 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7859,7 +7859,7 @@ dependencies = [ [[package]] name = "katana" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -7867,7 +7867,7 @@ dependencies = [ "cfg-if", "clap", "clap_complete", - "common 0.7.0-alpha.5", + "common 0.7.0", "console", "dojo-metrics", "katana-core", @@ -7886,7 +7886,7 @@ dependencies = [ [[package]] name = "katana-cairo" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "cairo-lang-casm 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", "cairo-lang-runner 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", @@ -7899,7 +7899,7 @@ dependencies = [ [[package]] name = "katana-codecs" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "bytes", "katana-primitives", @@ -7907,7 +7907,7 @@ dependencies = [ [[package]] name = "katana-codecs-derive" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "proc-macro2", "quote", @@ -7917,7 +7917,7 @@ dependencies = [ [[package]] name = "katana-core" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-contract", "alloy-network", @@ -7965,7 +7965,7 @@ dependencies = [ [[package]] name = "katana-db" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7987,7 +7987,7 @@ dependencies = [ [[package]] name = "katana-executor" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -8014,7 +8014,7 @@ dependencies = [ [[package]] name = "katana-primitives" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -8039,7 +8039,7 @@ dependencies = [ [[package]] name = "katana-provider" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -8065,7 +8065,7 @@ dependencies = [ [[package]] name = "katana-rpc" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_matches", @@ -8103,7 +8103,7 @@ dependencies = [ [[package]] name = "katana-rpc-api" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "jsonrpsee 0.16.3", "katana-core", @@ -8114,7 +8114,7 @@ dependencies = [ [[package]] name = "katana-rpc-types" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -8135,7 +8135,7 @@ dependencies = [ [[package]] name = "katana-rpc-types-builder" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "katana-executor", @@ -8147,7 +8147,7 @@ dependencies = [ [[package]] name = "katana-runner" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_fs", @@ -8166,7 +8166,7 @@ dependencies = [ [[package]] name = "katana-tasks" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "futures", "rayon", @@ -11545,7 +11545,7 @@ checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "runner-macro" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "quote", "syn 2.0.64", @@ -11813,7 +11813,7 @@ dependencies = [ [[package]] name = "saya" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "cairo-proof-parser", @@ -11834,7 +11834,7 @@ dependencies = [ [[package]] name = "saya-core" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-trait", @@ -11876,7 +11876,7 @@ dependencies = [ [[package]] name = "saya-provider" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "alloy-primitives", "anyhow", @@ -12048,7 +12048,7 @@ dependencies = [ [[package]] name = "scheduler" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "clap", "clap_complete", @@ -12684,7 +12684,7 @@ dependencies = [ [[package]] name = "sozo" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_fs", @@ -12743,7 +12743,7 @@ dependencies = [ [[package]] name = "sozo-ops" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "assert_fs", @@ -12799,7 +12799,7 @@ dependencies = [ [[package]] name = "sozo-signers" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "starknet", @@ -14070,7 +14070,7 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "torii" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-trait", @@ -14078,7 +14078,7 @@ dependencies = [ "camino", "chrono", "clap", - "common 0.7.0-alpha.5", + "common 0.7.0", "ctrlc", "dojo-metrics", "dojo-types", @@ -14115,7 +14115,7 @@ dependencies = [ [[package]] name = "torii-client" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "async-trait", "camino", @@ -14143,7 +14143,7 @@ dependencies = [ [[package]] name = "torii-core" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-trait", @@ -14182,7 +14182,7 @@ dependencies = [ [[package]] name = "torii-graphql" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-graphql", @@ -14223,7 +14223,7 @@ dependencies = [ [[package]] name = "torii-grpc" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "bytes", "camino", @@ -14267,7 +14267,7 @@ dependencies = [ [[package]] name = "torii-relay" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-trait", @@ -14303,7 +14303,7 @@ dependencies = [ [[package]] name = "torii-server" -version = "0.7.0-alpha.5" +version = "0.7.0" dependencies = [ "anyhow", "async-trait", @@ -14626,7 +14626,7 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "types-test" -version = "0.7.0-alpha.5" +version = "0.7.0" [[package]] name = "ucd-trie" diff --git a/Cargo.toml b/Cargo.toml index cec0e4cd65..49ea3d3980 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ edition = "2021" license = "Apache-2.0" license-file = "LICENSE" repository = "https://github.com/dojoengine/dojo/" -version = "0.7.0-alpha.5" +version = "0.7.0" [profile.performance] codegen-units = 1 diff --git a/crates/dojo-core/Scarb.lock b/crates/dojo-core/Scarb.lock index 87f054ddd0..8f50ef208b 100644 --- a/crates/dojo-core/Scarb.lock +++ b/crates/dojo-core/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo_plugin", ] diff --git a/crates/dojo-core/Scarb.toml b/crates/dojo-core/Scarb.toml index 9e23066bca..ddc8fb6569 100644 --- a/crates/dojo-core/Scarb.toml +++ b/crates/dojo-core/Scarb.toml @@ -2,7 +2,7 @@ cairo-version = "=2.6.3" description = "The Dojo Core library for autonomous worlds." name = "dojo" -version = "0.6.0" +version = "0.7.0" [dependencies] dojo_plugin = { git = "https://github.com/dojoengine/dojo", tag = "v0.3.11" } diff --git a/crates/katana/runner/runner-macro/Cargo.toml b/crates/katana/runner/runner-macro/Cargo.toml index 3b7767c142..18bf78b403 100644 --- a/crates/katana/runner/runner-macro/Cargo.toml +++ b/crates/katana/runner/runner-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runner-macro" -version = "0.7.0-alpha.5" +version = "0.7.0" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index 112ae6dbe9..0babbac9af 100644 --- a/crates/torii/types-test/Scarb.lock +++ b/crates/torii/types-test/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo_plugin", ] diff --git a/crates/torii/types-test/Scarb.toml b/crates/torii/types-test/Scarb.toml index 0f11558350..1e34e4f328 100644 --- a/crates/torii/types-test/Scarb.toml +++ b/crates/torii/types-test/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "2.4.0" name = "types_test" -version = "0.6.0" +version = "0.7.0" [cairo] sierra-replace-ids = true diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 9525e9db0e..d3ebe55642 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo_plugin", ] diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index 5dd277ffa0..27de8bbe1d 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "=2.6.3" name = "dojo_examples" -version = "0.6.0" +version = "0.7.0" # Use the prelude with the less imports as possible # from corelib. edition = "2023_10" From 485711337b982ed9cd4c36e7a516c340febec48d Mon Sep 17 00:00:00 2001 From: glihm Date: Thu, 13 Jun 2024 20:01:32 -0600 Subject: [PATCH 10/32] fix: ensure pkg-config is also installed (#2056) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9e733fc12f..ea0ccacc32 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -92,7 +92,7 @@ jobs: if: ${{ matrix.job.target == 'aarch64-unknown-linux-gnu' }} run: | sudo apt-get update -y - sudo apt-get install -y gcc-aarch64-linux-gnu libssl-dev + sudo apt-get install -y gcc-aarch64-linux-gnu libssl-dev pkg-config echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV # We build jemalloc with 64KB pagesize so that it works for all linux/arm64 pagesize variants # See: https://github.com/jemalloc/jemalloc/issues/467 From 34b13caa785c1149558d28f1a9d9fbd700c4aa2d Mon Sep 17 00:00:00 2001 From: glihm Date: Thu, 13 Jun 2024 20:31:29 -0600 Subject: [PATCH 11/32] ci: try arm64 ubuntu runner --- .github/workflows/release.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea0ccacc32..ee55da80f6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -46,7 +46,7 @@ jobs: platform: linux target: x86_64-unknown-linux-gnu arch: amd64 - - os: ubuntu-latest-8-cores + - os: ubuntu-latest-8-cores-arm64 platform: linux target: aarch64-unknown-linux-gnu arch: arm64 @@ -92,8 +92,7 @@ jobs: if: ${{ matrix.job.target == 'aarch64-unknown-linux-gnu' }} run: | sudo apt-get update -y - sudo apt-get install -y gcc-aarch64-linux-gnu libssl-dev pkg-config - echo "CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc" >> $GITHUB_ENV + sudo apt-get install -y gcc-aarch64-linux-gnu libssl-dev # We build jemalloc with 64KB pagesize so that it works for all linux/arm64 pagesize variants # See: https://github.com/jemalloc/jemalloc/issues/467 echo "JEMALLOC_SYS_WITH_LG_PAGE=16" >> $GITHUB_ENV From 0e9497516d6afe4c749b20695b309e763907357b Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Fri, 14 Jun 2024 16:43:35 -0400 Subject: [PATCH 12/32] Update devcontainer image: v0.7.0 (#2052) Co-authored-by: glihm --- .devcontainer/devcontainer.json | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/release-dispatch.yml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 176190883c..b71e0f6aa2 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust { "name": "Rust", - "image": "ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5", + "image": "ghcr.io/dojoengine/dojo-dev:v0.7.0", "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 904d05fc3a..16b8df0133 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 85f421dbfa..53876adc6e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: test: runs-on: ubuntu-latest-32-cores container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -33,7 +33,7 @@ jobs: ensure-wasm: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -67,7 +67,7 @@ jobs: dojo-core-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -76,7 +76,7 @@ jobs: dojo-spawn-and-move-example-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -85,7 +85,7 @@ jobs: dojo-world-bindings-check: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -94,7 +94,7 @@ jobs: clippy: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -103,7 +103,7 @@ jobs: fmt: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -112,7 +112,7 @@ jobs: docs: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/release-dispatch.yml b/.github/workflows/release-dispatch.yml index 944accd1ea..6374f2428a 100644 --- a/.github/workflows/release-dispatch.yml +++ b/.github/workflows/release-dispatch.yml @@ -14,7 +14,7 @@ jobs: contents: write runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0-alpha.5 + image: ghcr.io/dojoengine/dojo-dev:v0.7.0 env: VERSION: "" steps: From cab4d0541dd42df7570ac91d6fba9967e5ba1d2f Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Fri, 14 Jun 2024 18:01:59 -0400 Subject: [PATCH 13/32] fix(dojo-bindgen): array length before array items (#2060) fix: include array length before array items --- crates/dojo-bindgen/src/plugins/unity/mod.rs | 36 ++++++++++++-------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/crates/dojo-bindgen/src/plugins/unity/mod.rs b/crates/dojo-bindgen/src/plugins/unity/mod.rs index 45578f2267..8fe748a940 100644 --- a/crates/dojo-bindgen/src/plugins/unity/mod.rs +++ b/crates/dojo-bindgen/src/plugins/unity/mod.rs @@ -364,20 +364,28 @@ public class {} : ModelInstance {{ .collect::>() .join(", "); - vec![( - if is_inner_array { - format!( - "{arg_name}.SelectMany({arg_name}Item => new dojo.FieldElement[] \ - {{ }}.Concat({inners}))" - ) - } else { - format!( - "{arg_name}.SelectMany({arg_name}Item => new [] {{ {inners} }})" - ) - }, - true, - enum_variant.clone(), - )] + vec![ + ( + format!("new FieldElement({arg_name}.Length).Inner",), + false, + enum_variant.clone(), + ), + ( + if is_inner_array { + format!( + "{arg_name}.SelectMany({arg_name}Item => new \ + dojo.FieldElement[] {{ }}.Concat({inners}))" + ) + } else { + format!( + "{arg_name}.SelectMany({arg_name}Item => new [] {{ {inners} \ + }})" + ) + }, + true, + enum_variant.clone(), + ), + ] } Token::Tuple(tuple) => tuple .inners From 25e857365c8f61c21bb714e4c9e9e44e433658e5 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Sat, 15 Jun 2024 15:55:32 -0400 Subject: [PATCH 14/32] fix(torii): fix table name using reserved sql keywords (#2062) --- crates/torii/core/src/sql.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/torii/core/src/sql.rs b/crates/torii/core/src/sql.rs index e0d89bf3b4..7f54ae28b6 100644 --- a/crates/torii/core/src/sql.rs +++ b/crates/torii/core/src/sql.rs @@ -936,7 +936,7 @@ impl Sql { create_table_query.push_str(&format!(", idx_{i}", i = i)); } create_table_query.push_str(&format!( - ") REFERENCES {parent_table_id} (id", + ") REFERENCES [{parent_table_id}] (id", parent_table_id = parent_table_id )); for i in 0..parent_array_idx { From 3c661bd55afe132a8e7e6806869f7fd7558850d9 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Sun, 16 Jun 2024 18:18:59 +0800 Subject: [PATCH 15/32] refactor(sozo): dont use explicit account type (#2061) * use account with trait * remove comments * fmt * remove comments * update dev as well --------- Co-authored-by: lambda-0x <0xlambda@protonmail.com> --- bin/sozo/src/commands/dev.rs | 13 ++-- crates/dojo-world/src/migration/mod.rs | 49 ++++++------ crates/sozo/ops/src/auth.rs | 9 ++- crates/sozo/ops/src/migration/auto_auth.rs | 7 +- crates/sozo/ops/src/migration/migrate.rs | 87 +++++++++++----------- crates/sozo/ops/src/migration/mod.rs | 13 ++-- crates/sozo/ops/src/migration/utils.rs | 12 ++- examples/spawn-and-move/Scarb.lock | 2 +- 8 files changed, 95 insertions(+), 97 deletions(-) diff --git a/bin/sozo/src/commands/dev.rs b/bin/sozo/src/commands/dev.rs index 79d866b1a0..3a80a75f96 100644 --- a/bin/sozo/src/commands/dev.rs +++ b/bin/sozo/src/commands/dev.rs @@ -19,10 +19,8 @@ use scarb::compiler::{CairoCompilationUnit, CompilationUnit, CompilationUnitAttr use scarb::core::{Config, Workspace}; use scarb::ops::{FeaturesOpts, FeaturesSelector}; use sozo_ops::migration; -use starknet::accounts::SingleOwnerAccount; +use starknet::accounts::ConnectedAccount; use starknet::core::types::FieldElement; -use starknet::providers::Provider; -use starknet::signers::Signer; use tracing::{error, trace}; use super::migrate::setup_env; @@ -225,17 +223,18 @@ fn build(context: &mut DevContext<'_>) -> Result<()> { } // TODO: fix me -async fn migrate( +async fn migrate( mut world_address: Option, - account: &SingleOwnerAccount, + account: A, name: &str, ws: &Workspace<'_>, previous_manifest: Option, skip_migration: Option>, ) -> Result<(DeploymentManifest, Option)> where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + A::Provider: Send, + A::SignError: 'static, { let target_dir = ws.target_dir().path_existent().unwrap(); let target_dir = target_dir.join(ws.config().profile().as_str()); diff --git a/crates/dojo-world/src/migration/mod.rs b/crates/dojo-world/src/migration/mod.rs index 4f6b306bad..203b5d91de 100644 --- a/crates/dojo-world/src/migration/mod.rs +++ b/crates/dojo-world/src/migration/mod.rs @@ -7,7 +7,7 @@ use anyhow::{anyhow, Result}; use async_trait::async_trait; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use cairo_lang_starknet_classes::contract_class::ContractClass; -use starknet::accounts::{Account, AccountError, Call, ConnectedAccount, SingleOwnerAccount}; +use starknet::accounts::{Account, AccountError, Call, ConnectedAccount}; use starknet::core::types::contract::{CompiledClass, SierraClass}; use starknet::core::types::{ BlockId, BlockTag, DeclareTransactionResult, FieldElement, FlattenedSierraClass, @@ -16,7 +16,6 @@ use starknet::core::types::{ use starknet::core::utils::{get_contract_address, CairoShortStringToFeltError}; use starknet::macros::{felt, selector}; use starknet::providers::{Provider, ProviderError}; -use starknet::signers::Signer; use thiserror::Error; use crate::utils::{TransactionExt, TransactionWaiter, TransactionWaitingError}; @@ -127,14 +126,14 @@ impl TxnConfig { #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] pub trait Declarable { - async fn declare( + async fn declare( &self, - account: &SingleOwnerAccount, + account: A, txn_config: &TxnConfig, - ) -> Result as Account>::SignError>> + ) -> Result::SignError>> where - P: Provider + Sync + Send, - S: Signer + Sync + Send, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { let (flattened_class, casm_class_hash) = prepare_contract_declaration_params(self.artifact_path())?; @@ -168,20 +167,20 @@ pub trait Declarable { #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] pub trait Deployable: Declarable + Sync { - async fn deploy_dojo_contract( + async fn deploy_dojo_contract( &self, world_address: FieldElement, class_hash: FieldElement, base_class_hash: FieldElement, - account: &SingleOwnerAccount, + account: A, txn_config: &TxnConfig, calldata: &[String], - ) -> Result as Account>::SignError>> + ) -> Result::SignError>> where - P: Provider + Sync + Send, - S: Signer + Sync + Send, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { - let declare = match self.declare(account, txn_config).await { + let declare = match self.declare(&account, txn_config).await { Ok(res) => Some(res), Err(MigrationError::ClassAlreadyDeclared) => None, Err(e) => return Err(e), @@ -247,18 +246,18 @@ pub trait Deployable: Declarable + Sync { }) } - async fn deploy( + async fn deploy( &self, class_hash: FieldElement, constructor_calldata: Vec, - account: &SingleOwnerAccount, + account: A, txn_config: &TxnConfig, - ) -> Result as Account>::SignError>> + ) -> Result::SignError>> where - P: Provider + Sync + Send, - S: Signer + Sync + Send, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { - let declare = match self.declare(account, txn_config).await { + let declare = match self.declare(&account, txn_config).await { Ok(res) => Some(res), Err(MigrationError::ClassAlreadyDeclared) => None, Err(e) => return Err(e), @@ -322,19 +321,19 @@ pub trait Deployable: Declarable + Sync { #[cfg_attr(not(target_arch = "wasm32"), async_trait)] #[cfg_attr(target_arch = "wasm32", async_trait(?Send))] pub trait Upgradable: Deployable + Declarable + Sync { - async fn upgrade_world( + async fn upgrade_world( &self, class_hash: FieldElement, original_class_hash: FieldElement, original_base_class_hash: FieldElement, - account: &SingleOwnerAccount, + account: A, txn_config: &TxnConfig, - ) -> Result as Account>::SignError>> + ) -> Result::SignError>> where - P: Provider + Sync + Send, - S: Signer + Sync + Send, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { - let declare = match self.declare(account, txn_config).await { + let declare = match self.declare(&account, txn_config).await { Ok(res) => Some(res), Err(MigrationError::ClassAlreadyDeclared) => None, Err(e) => return Err(e), diff --git a/crates/sozo/ops/src/auth.rs b/crates/sozo/ops/src/auth.rs index 35c805376f..9edb851b48 100644 --- a/crates/sozo/ops/src/auth.rs +++ b/crates/sozo/ops/src/auth.rs @@ -7,7 +7,7 @@ use dojo_world::contracts::{cairo_utils, WorldContractReader}; use dojo_world::migration::TxnConfig; use dojo_world::utils::TransactionExt; use scarb_ui::Ui; -use starknet::accounts::ConnectedAccount; +use starknet::accounts::{Account, ConnectedAccount}; use starknet::core::types::{BlockId, BlockTag}; use starknet::core::utils::{get_selector_from_name, parse_cairo_short_string}; use starknet_crypto::FieldElement; @@ -88,14 +88,15 @@ impl FromStr for OwnerResource { } } -pub async fn grant_writer( - ui: &Ui, +pub async fn grant_writer<'a, A>( + ui: &'a Ui, world: &WorldContract, models_contracts: Vec, txn_config: TxnConfig, ) -> Result<()> where - A: ConnectedAccount + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + ::SignError: 'static, { let mut calls = Vec::new(); diff --git a/crates/sozo/ops/src/migration/auto_auth.rs b/crates/sozo/ops/src/migration/auto_auth.rs index 08d67772d9..df213e144c 100644 --- a/crates/sozo/ops/src/migration/auto_auth.rs +++ b/crates/sozo/ops/src/migration/auto_auth.rs @@ -10,15 +10,16 @@ use super::ui::MigrationUi; use super::MigrationOutput; use crate::auth::{grant_writer, ModelContract}; -pub async fn auto_authorize<'a, A>( +pub async fn auto_authorize( ws: &Workspace<'_>, - world: &'a WorldContract, + world: &WorldContract, txn_config: &TxnConfig, local_manifest: &BaseManifest, migration_output: &MigrationOutput, ) -> Result<()> where - A: ConnectedAccount + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + A::SignError: 'static, { let ui = ws.config().ui(); diff --git a/crates/sozo/ops/src/migration/migrate.rs b/crates/sozo/ops/src/migration/migrate.rs index b6c194e5a4..eb0b406b42 100644 --- a/crates/sozo/ops/src/migration/migrate.rs +++ b/crates/sozo/ops/src/migration/migrate.rs @@ -21,7 +21,7 @@ use dojo_world::utils::{TransactionExt, TransactionWaiter}; use futures::future; use scarb::core::Workspace; use scarb_ui::Ui; -use starknet::accounts::{Account, ConnectedAccount, SingleOwnerAccount}; +use starknet::accounts::ConnectedAccount; use starknet::core::types::{ BlockId, BlockTag, FunctionCall, InvokeTransactionResult, StarknetError, }; @@ -29,7 +29,6 @@ use starknet::core::utils::{ cairo_short_string_to_felt, get_contract_address, get_selector_from_name, }; use starknet::providers::{Provider, ProviderError}; -use starknet::signers::Signer; use starknet_crypto::FieldElement; use tokio::fs; @@ -64,15 +63,16 @@ pub fn prepare_migration( Ok(migration) } -pub async fn apply_diff( +pub async fn apply_diff( ws: &Workspace<'_>, - account: &SingleOwnerAccount, + account: A, txn_config: TxnConfig, strategy: &mut MigrationStrategy, ) -> Result where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + ::Provider: Send, + A::SignError: 'static, { let ui = ws.config().ui(); @@ -116,15 +116,16 @@ where Ok(migration_output) } -pub async fn execute_strategy( +pub async fn execute_strategy( ws: &Workspace<'_>, strategy: &MigrationStrategy, - migrator: &SingleOwnerAccount, + migrator: A, txn_config: TxnConfig, ) -> Result where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + A::Provider: Send, + A::SignError: 'static, { let ui = ws.config().ui(); let mut world_tx_hash: Option = None; @@ -134,7 +135,7 @@ where Some(base) => { ui.print_header("# Base Contract"); - match base.declare(migrator, &txn_config).await { + match base.declare(&migrator, &txn_config).await { Ok(res) => { ui.print_sub(format!("Class Hash: {:#x}", res.class_hash)); } @@ -165,7 +166,7 @@ where "world", world.diff.original_class_hash, strategy.base.as_ref().unwrap().diff.original_class_hash, - migrator, + &migrator, &ui, &txn_config, ) @@ -182,7 +183,7 @@ where } else { let calldata = vec![strategy.base.as_ref().unwrap().diff.local_class_hash]; let deploy_result = - deploy_contract(world, "world", calldata.clone(), migrator, &ui, &txn_config) + deploy_contract(world, "world", calldata.clone(), &migrator, &ui, &txn_config) .await .map_err(|e| { ui.verbose(format!("{e:?}")); @@ -215,7 +216,7 @@ where // Once Torii supports indexing arrays, we should declare and register the // ResourceMetadata model. - match register_dojo_models(&strategy.models, world_address, migrator, &ui, &txn_config).await { + match register_dojo_models(&strategy.models, world_address, &migrator, &ui, &txn_config).await { Ok(output) => { migration_output.models = output.registered_model_names; } @@ -292,15 +293,15 @@ fn create_resource_metadata( /// * `ws` - the workspace /// * `migrator` - the account used to migrate /// * `migration_output` - the output after having applied the migration plan. -pub async fn upload_metadata( +pub async fn upload_metadata( ws: &Workspace<'_>, - migrator: &SingleOwnerAccount, + migrator: A, migration_output: MigrationOutput, txn_config: TxnConfig, ) -> Result<()> where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + ::Provider: Send, { let ui = ws.config().ui(); @@ -364,7 +365,7 @@ where ui.print("> All IPFS artifacts have been successfully uploaded.".to_string()); // update the resource registry - let world = WorldContract::new(migration_output.world_address, migrator); + let world = WorldContract::new(migration_output.world_address, &migrator); let calls = resources.iter().map(|r| world.set_metadata_getcall(r)).collect::>(); @@ -387,16 +388,16 @@ where Ok(()) } -async fn register_dojo_models( +async fn register_dojo_models( models: &[ClassMigration], world_address: FieldElement, - migrator: &SingleOwnerAccount, + migrator: A, ui: &Ui, txn_config: &TxnConfig, ) -> Result where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { if models.is_empty() { return Ok(RegisterOutput { @@ -414,7 +415,7 @@ where for c in models.iter() { ui.print(italic_message(&c.diff.name).to_string()); - let res = c.declare(migrator, txn_config).await; + let res = c.declare(&migrator, txn_config).await; match res { Ok(output) => { ui.print_hidden_sub(format!("Declare transaction: {:#x}", output.transaction_hash)); @@ -439,7 +440,7 @@ where ui.print_sub(format!("Class hash: {:#x}", c.diff.local_class_hash)); } - let world = WorldContract::new(world_address, migrator); + let world = WorldContract::new(world_address, &migrator); let calls = models .iter() @@ -462,16 +463,16 @@ where Ok(RegisterOutput { transaction_hash, declare_output, registered_model_names }) } -async fn register_dojo_contracts( +async fn register_dojo_contracts( contracts: &Vec, world_address: FieldElement, - migrator: &SingleOwnerAccount, + migrator: A, ui: &Ui, txn_config: &TxnConfig, ) -> Result>> where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { if contracts.is_empty() { return Ok(vec![]); @@ -489,7 +490,7 @@ where world_address, contract.diff.local_class_hash, contract.diff.base_class_hash, - migrator, + &migrator, txn_config, &contract.diff.init_calldata, ) @@ -550,17 +551,17 @@ where Ok(deploy_output) } -async fn deploy_contract( +async fn deploy_contract( contract: &ContractMigration, contract_id: &str, constructor_calldata: Vec, - migrator: &SingleOwnerAccount, + migrator: A, ui: &Ui, txn_config: &TxnConfig, ) -> Result where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { match contract .deploy(contract.diff.local_class_hash, constructor_calldata, migrator, txn_config) @@ -592,18 +593,18 @@ where } } -async fn upgrade_contract( +async fn upgrade_contract( contract: &ContractMigration, contract_id: &str, original_class_hash: FieldElement, original_base_class_hash: FieldElement, - migrator: &SingleOwnerAccount, + migrator: A, ui: &Ui, txn_config: &TxnConfig, ) -> Result where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Send + Sync, + ::Provider: Send, { match contract .upgrade_world( @@ -649,12 +650,12 @@ pub fn handle_artifact_error(ui: &Ui, artifact_path: &Path, error: anyhow::Error } pub async fn get_contract_operation_name

( - provider: &P, + provider: P, contract: &ContractMigration, world_address: Option, ) -> String where - P: Provider + Sync + Send + 'static, + P: Provider + Sync + Send, { if let Some(world_address) = world_address { if let Ok(base_class_hash) = provider @@ -691,11 +692,11 @@ where pub async fn print_strategy

( ui: &Ui, - provider: &P, + provider: P, strategy: &MigrationStrategy, world_address: FieldElement, ) where - P: Provider + Sync + Send + 'static, + P: Provider + Sync + Send, { ui.print("\n📋 Migration Strategy\n"); @@ -730,7 +731,7 @@ pub async fn print_strategy

( if !&strategy.contracts.is_empty() { ui.print_header(format!("# Contracts ({})", &strategy.contracts.len())); for c in &strategy.contracts { - let op_name = get_contract_operation_name(provider, c, strategy.world_address).await; + let op_name = get_contract_operation_name(&provider, c, strategy.world_address).await; ui.print(op_name); ui.print_sub(format!("Class hash: {:#x}", c.diff.local_class_hash)); diff --git a/crates/sozo/ops/src/migration/mod.rs b/crates/sozo/ops/src/migration/mod.rs index 393ec72785..21351004a2 100644 --- a/crates/sozo/ops/src/migration/mod.rs +++ b/crates/sozo/ops/src/migration/mod.rs @@ -12,10 +12,8 @@ use dojo_world::manifest::{ use dojo_world::migration::world::WorldDiff; use dojo_world::migration::{DeployOutput, TxnConfig, UpgradeOutput}; use scarb::core::Workspace; -use starknet::accounts::{ConnectedAccount, SingleOwnerAccount}; +use starknet::accounts::ConnectedAccount; use starknet::core::types::FieldElement; -use starknet::providers::Provider; -use starknet::signers::Signer; mod auto_auth; mod migrate; @@ -50,19 +48,20 @@ pub struct ContractMigrationOutput { } #[allow(clippy::too_many_arguments)] -pub async fn migrate( +pub async fn migrate( ws: &Workspace<'_>, world_address: Option, rpc_url: String, - account: SingleOwnerAccount, + account: A, name: &str, dry_run: bool, txn_config: TxnConfig, skip_manifests: Option>, ) -> Result<()> where - P: Provider + Sync + Send + 'static, - S: Signer + Sync + Send + 'static, + A: ConnectedAccount + Sync + Send, + A::Provider: Send, + A::SignError: 'static, { let ui = ws.config().ui(); diff --git a/crates/sozo/ops/src/migration/utils.rs b/crates/sozo/ops/src/migration/utils.rs index e8f6f50165..1afe38f305 100644 --- a/crates/sozo/ops/src/migration/utils.rs +++ b/crates/sozo/ops/src/migration/utils.rs @@ -5,9 +5,7 @@ use dojo_world::manifest::{ OVERLAYS_DIR, }; use scarb_ui::Ui; -use starknet::accounts::{ConnectedAccount, SingleOwnerAccount}; -use starknet::providers::Provider; -use starknet::signers::Signer; +use starknet::accounts::ConnectedAccount; use starknet_crypto::FieldElement; use super::ui::MigrationUi; @@ -15,16 +13,16 @@ use super::ui::MigrationUi; /// Loads: /// - `BaseManifest` from filesystem /// - `DeployedManifest` from onchain dataa if `world_address` is `Some` -pub(super) async fn load_world_manifests( +pub(super) async fn load_world_manifests( profile_dir: &Utf8PathBuf, - account: &SingleOwnerAccount, + account: A, world_address: Option, ui: &Ui, skip_migration: Option>, ) -> Result<(BaseManifest, Option)> where - P: Provider + Sync + Send, - S: Signer + Sync + Send, + A: ConnectedAccount + Sync + Send, + ::Provider: Send, { ui.print_step(1, "🌎", "Building World state..."); diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index d3ebe55642..427bc2e0e4 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -10,7 +10,7 @@ dependencies = [ [[package]] name = "dojo_examples" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo", ] From 88848efd9a3ecd7b85413d52cfe354c070ccc12a Mon Sep 17 00:00:00 2001 From: glihm Date: Sun, 16 Jun 2024 04:19:22 -0600 Subject: [PATCH 16/32] fix(sozo): allow sozo build in workspace and proper error for other cases (#2059) * fix: use default value instead of unwrap * wip: unlocking build in workspace + prepare workspace support * update implementations * fix tests * use current_package instead of root_package * update comments --------- Co-authored-by: lambda-0x <0xlambda@protonmail.com> --- bin/sozo/src/commands/build.rs | 14 +++++++------- bin/sozo/src/commands/clean.rs | 4 +++- bin/sozo/src/commands/dev.rs | 11 +++++++++-- bin/sozo/src/commands/migrate.rs | 12 ++++++++++-- bin/sozo/src/commands/print_env.rs | 13 +++++++++++-- bin/sozo/src/utils.rs | 13 ++++++++++--- bin/sozo/tests/register_test.rs | 8 ++++++-- crates/dojo-bindgen/src/lib.rs | 5 ++++- .../dojo-bindgen/src/plugins/typescript_v2/mod.rs | 5 ++++- .../manifest_test_data/compiler_cairo/Scarb.lock | 2 +- crates/dojo-test-utils/src/migration.rs | 5 ++++- crates/dojo-world/src/contracts/model_test.rs | 3 ++- crates/dojo-world/src/contracts/world_test.rs | 3 ++- crates/dojo-world/src/manifest/manifest_test.rs | 3 ++- crates/dojo-world/src/metadata.rs | 13 ++++++++++--- crates/dojo-world/src/metadata_test.rs | 3 ++- crates/sozo/ops/src/migration/migrate.rs | 6 +++++- crates/sozo/ops/src/tests/migration.rs | 3 ++- crates/torii/core/src/sql_test.rs | 3 ++- crates/torii/graphql/src/tests/mod.rs | 3 ++- .../torii/grpc/src/server/tests/entities_test.rs | 3 ++- 21 files changed, 100 insertions(+), 35 deletions(-) diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index b94785575e..5d1d5df7cf 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -126,13 +126,13 @@ impl BuildArgs { }; trace!(pluginManager=?bindgen, "Generating bindings."); - let ws = scarb::ops::read_workspace(config.manifest_path(), config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); - - tokio::runtime::Runtime::new() - .unwrap() - .block_on(bindgen.generate(dojo_metadata.skip_migration)) - .expect("Error generating bindings"); + // Only generate bindgen if a current package is defined with dojo metadata. + if let Some(dojo_metadata) = dojo_metadata_from_workspace(&ws) { + tokio::runtime::Runtime::new() + .unwrap() + .block_on(bindgen.generate(dojo_metadata.skip_migration)) + .expect("Error generating bindings"); + }; Ok(()) } diff --git a/bin/sozo/src/commands/clean.rs b/bin/sozo/src/commands/clean.rs index 41da4a1921..bf44226bb8 100644 --- a/bin/sozo/src/commands/clean.rs +++ b/bin/sozo/src/commands/clean.rs @@ -85,7 +85,9 @@ mod tests { let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = dojo_metadata_from_workspace(&ws).expect( + "No current package with dojo metadata found, clean is not yet support for workspaces.", + ); // Plan the migration to generate some manifests other than base. config.tokio_handle().block_on(async { diff --git a/bin/sozo/src/commands/dev.rs b/bin/sozo/src/commands/dev.rs index 3a80a75f96..92b20e7c66 100644 --- a/bin/sozo/src/commands/dev.rs +++ b/bin/sozo/src/commands/dev.rs @@ -48,7 +48,14 @@ pub struct DevArgs { impl DevArgs { pub fn run(self, config: &Config) -> Result<()> { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(&ws) { + metadata + } else { + return Err(anyhow!( + "No current package with dojo metadata found, dev is not yet support for \ + workspaces." + )); + }; let env_metadata = if config.manifest_path().exists() { dojo_metadata.env().cloned() @@ -67,7 +74,7 @@ impl DevArgs { RecursiveMode::Recursive, )?; - let name = self.name.unwrap_or_else(|| ws.root_package().unwrap().id.name.to_string()); + let name = self.name.unwrap_or_else(|| ws.current_package().unwrap().id.name.to_string()); let mut previous_manifest: Option = Option::None; let result = build(&mut context); diff --git a/bin/sozo/src/commands/migrate.rs b/bin/sozo/src/commands/migrate.rs index 6f6abe7404..239a78f58d 100644 --- a/bin/sozo/src/commands/migrate.rs +++ b/bin/sozo/src/commands/migrate.rs @@ -58,7 +58,15 @@ impl MigrateArgs { pub fn run(self, config: &Config) -> Result<()> { trace!(args = ?self); let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let dojo_metadata = dojo_metadata_from_workspace(&ws); + + let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(&ws) { + metadata + } else { + return Err(anyhow!( + "No current package with dojo metadata found, migrate is not yet support for \ + workspaces." + )); + }; // This variant is tested before the match on `self.command` to avoid // having the need to spin up a Katana to generate the files. @@ -82,7 +90,7 @@ impl MigrateArgs { let MigrateArgs { name, world, starknet, account, .. } = self; let name = name.unwrap_or_else(|| { - ws.root_package().expect("Root package to be present").id.name.to_string() + ws.current_package().expect("Root package to be present").id.name.to_string() }); let (world_address, account, rpc_url) = config.tokio_handle().block_on(async { diff --git a/bin/sozo/src/commands/print_env.rs b/bin/sozo/src/commands/print_env.rs index 23c273fe57..f8be7e1df4 100644 --- a/bin/sozo/src/commands/print_env.rs +++ b/bin/sozo/src/commands/print_env.rs @@ -1,4 +1,4 @@ -use anyhow::Result; +use anyhow::{anyhow, Result}; use clap::Args; use dojo_world::metadata::dojo_metadata_from_workspace; use scarb::core::Config; @@ -26,8 +26,17 @@ impl PrintEnvArgs { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; let ui = ws.config().ui(); + let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(&ws) { + metadata + } else { + return Err(anyhow!( + "No current package with dojo metadata found, print-env is not yet support for \ + workspaces." + )); + }; + let env_metadata = if config.manifest_path().exists() { - dojo_metadata_from_workspace(&ws).env().cloned() + dojo_metadata.env().cloned() } else { trace!("Manifest path does not exist."); None diff --git a/bin/sozo/src/utils.rs b/bin/sozo/src/utils.rs index d277c8d910..e65c0a2838 100644 --- a/bin/sozo/src/utils.rs +++ b/bin/sozo/src/utils.rs @@ -1,6 +1,6 @@ use std::str::FromStr; -use anyhow::{Error, Result}; +use anyhow::{anyhow, Error, Result}; use camino::Utf8PathBuf; use dojo_world::contracts::world::WorldContract; use dojo_world::contracts::WorldContractReader; @@ -28,8 +28,15 @@ use crate::commands::options::world::WorldOptions; pub fn load_metadata_from_config(config: &Config) -> Result, Error> { let env_metadata = if config.manifest_path().exists() { let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - - dojo_metadata_from_workspace(&ws).env().cloned() + let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(&ws) { + metadata + } else { + return Err(anyhow!( + "No current package with dojo metadata found, workspaces are not suppored yet." + )); + }; + + dojo_metadata.env().cloned() } else { None }; diff --git a/bin/sozo/tests/register_test.rs b/bin/sozo/tests/register_test.rs index 7faf1ce474..8cc161abee 100644 --- a/bin/sozo/tests/register_test.rs +++ b/bin/sozo/tests/register_test.rs @@ -21,13 +21,15 @@ async fn reregister_models() { let ws = ops::read_workspace(config.manifest_path(), &config) .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let target_path = ws.target_dir().path_existent().unwrap().join(ws.config().profile().to_string()); let migration = - prepare_migration(source_project_dir, target_path, dojo_metadata.skip_migration).unwrap(); + prepare_migration(source_project_dir.clone(), target_path, dojo_metadata.skip_migration) + .unwrap(); let sequencer = KatanaRunner::new().expect("Failed to start runner."); @@ -55,6 +57,8 @@ async fn reregister_models() { rpc_url, "--private-key", private_key, + "--manifest-path", + config.manifest_path().as_ref(), ]; let assert = get_snapbox().args(args_vec.iter()).assert().success(); diff --git a/crates/dojo-bindgen/src/lib.rs b/crates/dojo-bindgen/src/lib.rs index d92999ad14..c8cbe96172 100644 --- a/crates/dojo-bindgen/src/lib.rs +++ b/crates/dojo-bindgen/src/lib.rs @@ -274,7 +274,10 @@ mod tests { ); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = dojo_metadata_from_workspace(&ws).expect( + "No current package with dojo metadata found, bindgen is not yet supported for \ + workspaces.", + ); let data = gather_dojo_data(&manifest_path, "dojo_example", "dev", dojo_metadata.skip_migration) diff --git a/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs b/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs index 498b032c86..d7846ceef0 100644 --- a/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs +++ b/crates/dojo-bindgen/src/plugins/typescript_v2/mod.rs @@ -655,7 +655,10 @@ mod tests { ); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = dojo_metadata_from_workspace(&ws).expect( + "No current package with dojo metadata found, bindgen is not yet support for \ + workspaces.", + ); let data = gather_dojo_data(&manifest_path, "dojo_examples", "dev", dojo_metadata.skip_migration) .unwrap(); diff --git a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/Scarb.lock b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/Scarb.lock index 6f542bc33a..440bb61dbe 100644 --- a/crates/dojo-lang/src/manifest_test_data/compiler_cairo/Scarb.lock +++ b/crates/dojo-lang/src/manifest_test_data/compiler_cairo/Scarb.lock @@ -10,7 +10,7 @@ dependencies = [ [[package]] name = "dojo" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo_plugin", ] diff --git a/crates/dojo-test-utils/src/migration.rs b/crates/dojo-test-utils/src/migration.rs index 9edfb3e969..d0ecc91126 100644 --- a/crates/dojo-test-utils/src/migration.rs +++ b/crates/dojo-test-utils/src/migration.rs @@ -34,7 +34,10 @@ pub fn prepare_migration( let mut world = WorldDiff::compute(manifest, None); world.update_order().unwrap(); - prepare_for_migration(None, felt!("0x12345"), &target_dir, world) + let mut strat = prepare_for_migration(None, felt!("0x12345"), &target_dir, world).unwrap(); + strat.resolve_variable(strat.world_address().unwrap()).unwrap(); + + Ok(strat) } pub fn prepare_migration_with_world_and_seed( diff --git a/crates/dojo-world/src/contracts/model_test.rs b/crates/dojo-world/src/contracts/model_test.rs index 8aeeec1649..2fd460b729 100644 --- a/crates/dojo-world/src/contracts/model_test.rs +++ b/crates/dojo-world/src/contracts/model_test.rs @@ -26,7 +26,8 @@ async fn test_model() { let target_dir = manifest_dir.join("target").join("dev"); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let world_address = deploy_world(&runner, &manifest_dir.into(), &target_dir, dojo_metadata.skip_migration) diff --git a/crates/dojo-world/src/contracts/world_test.rs b/crates/dojo-world/src/contracts/world_test.rs index 21759c1ee2..5680d52c45 100644 --- a/crates/dojo-world/src/contracts/world_test.rs +++ b/crates/dojo-world/src/contracts/world_test.rs @@ -30,7 +30,8 @@ async fn test_world_contract_reader() { let provider = account.provider(); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let world_address = deploy_world( &runner, diff --git a/crates/dojo-world/src/manifest/manifest_test.rs b/crates/dojo-world/src/manifest/manifest_test.rs index b979b93675..d19a69b01b 100644 --- a/crates/dojo-world/src/manifest/manifest_test.rs +++ b/crates/dojo-world/src/manifest/manifest_test.rs @@ -384,7 +384,8 @@ fn fetch_remote_manifest() { compiler::copy_build_project_temp(source_project, dojo_core_path, true); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let artifacts_path = temp_project_dir.join(format!("target/{profile_name}")); diff --git a/crates/dojo-world/src/metadata.rs b/crates/dojo-world/src/metadata.rs index 12f6cc837f..d778476a2f 100644 --- a/crates/dojo-world/src/metadata.rs +++ b/crates/dojo-world/src/metadata.rs @@ -85,7 +85,7 @@ pub fn project_to_world_metadata(project_metadata: Option) /// /// # Returns /// A [`DojoMetadata`] object containing all Dojo metadata. -pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> DojoMetadata { +pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> Option { let profile = ws.config().profile(); let manifest_dir = ws.manifest_path().parent().unwrap().to_path_buf(); @@ -94,7 +94,14 @@ pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> DojoMetadata { let sources_dir = target_dir.join(profile.as_str()).join(SOURCES_DIR); let abis_dir = manifest_dir.join(ABIS_DIR).join(BASE_DIR); - let project_metadata = ws.current_package().unwrap().manifest.metadata.dojo(); + let project_metadata = if let Ok(current_package) = ws.current_package() { + current_package.manifest.metadata.dojo() + } else { + // On workspaces, dojo metadata are not accessible because if no current package is defined + // (being the only package or using --package). + return None; + }; + let mut dojo_metadata = DojoMetadata { env: project_metadata.env.clone(), skip_migration: project_metadata.skip_migration.clone(), @@ -142,7 +149,7 @@ pub fn dojo_metadata_from_workspace(ws: &Workspace<'_>) -> DojoMetadata { } } - dojo_metadata + Some(dojo_metadata) } /// Metadata coming from project configuration (Scarb.toml) diff --git a/crates/dojo-world/src/metadata_test.rs b/crates/dojo-world/src/metadata_test.rs index adeb0df9a7..e564e3a8e4 100644 --- a/crates/dojo-world/src/metadata_test.rs +++ b/crates/dojo-world/src/metadata_test.rs @@ -121,7 +121,8 @@ async fn get_full_dojo_metadata_from_workspace() { let sources_dir = target_dir.join(profile.as_str()).join(SOURCES_DIR); let abis_dir = manifest_dir.join(ABIS_DIR).join(BASE_DIR); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); // env assert!(dojo_metadata.env.is_some()); diff --git a/crates/sozo/ops/src/migration/migrate.rs b/crates/sozo/ops/src/migration/migrate.rs index eb0b406b42..420c269237 100644 --- a/crates/sozo/ops/src/migration/migrate.rs +++ b/crates/sozo/ops/src/migration/migrate.rs @@ -309,7 +309,11 @@ where ui.print_step(7, "🌐", "Uploading metadata..."); ui.print(" "); - let dojo_metadata = dojo_metadata_from_workspace(ws); + let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(ws) { + metadata + } else { + return Err(anyhow!("No current package with dojo metadata found.")); + }; let mut ipfs = vec![]; let mut resources = vec![]; diff --git a/crates/sozo/ops/src/tests/migration.rs b/crates/sozo/ops/src/tests/migration.rs index 006c9a731e..1c070dbd48 100644 --- a/crates/sozo/ops/src/tests/migration.rs +++ b/crates/sozo/ops/src/tests/migration.rs @@ -164,7 +164,8 @@ async fn migrate_with_metadata() { .unwrap_or_else(|_| panic!("Unable to initialize the IPFS Client")) .with_credentials(IPFS_USERNAME, IPFS_PASSWORD); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); // check world metadata let resource = world_reader.metadata(&FieldElement::ZERO).call().await.unwrap(); diff --git a/crates/torii/core/src/sql_test.rs b/crates/torii/core/src/sql_test.rs index cceb20d657..09f4100caa 100644 --- a/crates/torii/core/src/sql_test.rs +++ b/crates/torii/core/src/sql_test.rs @@ -63,7 +63,8 @@ async fn test_load_from_remote() { let config = compiler::copy_tmp_config(&source_project_dir, &dojo_core_path); let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let manifest_path = config.manifest_path(); let base_dir = manifest_path.parent().unwrap(); diff --git a/crates/torii/graphql/src/tests/mod.rs b/crates/torii/graphql/src/tests/mod.rs index 737cacc5ad..ddfc8fa182 100644 --- a/crates/torii/graphql/src/tests/mod.rs +++ b/crates/torii/graphql/src/tests/mod.rs @@ -286,7 +286,8 @@ pub async fn spinup_types_test() -> Result { let ws = ops::read_workspace(config.manifest_path(), &config) .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); let migration = diff --git a/crates/torii/grpc/src/server/tests/entities_test.rs b/crates/torii/grpc/src/server/tests/entities_test.rs index 786c1ffd1a..6d5cdbe9a1 100644 --- a/crates/torii/grpc/src/server/tests/entities_test.rs +++ b/crates/torii/grpc/src/server/tests/entities_test.rs @@ -44,7 +44,8 @@ async fn test_entities_queries() { let ws = ops::read_workspace(config.manifest_path(), &config) .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); - let dojo_metadata = dojo_metadata_from_workspace(&ws); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); let target_path = ws.target_dir().path_existent().unwrap().join(config.profile().to_string()); From 70ad72826df84cef73368cb38abda3d4715548dd Mon Sep 17 00:00:00 2001 From: lambda-0x <0xlambda@protonmail.com> Date: Mon, 17 Jun 2024 19:21:40 +0530 Subject: [PATCH 17/32] fix(migrate): when `init_calldata` depends on contract that was already deployed (#2058) * fix(migrate): when `init_calldata` depends on contract that was already deployed * add tests --- crates/dojo-world/src/migration/strategy.rs | 51 ++++++--- crates/sozo/ops/src/tests/migration.rs | 109 +++++++++++++++++++- crates/torii/types-test/Scarb.lock | 2 +- 3 files changed, 144 insertions(+), 18 deletions(-) diff --git a/crates/dojo-world/src/migration/strategy.rs b/crates/dojo-world/src/migration/strategy.rs index 2a1ce96155..258b34ea68 100644 --- a/crates/dojo-world/src/migration/strategy.rs +++ b/crates/dojo-world/src/migration/strategy.rs @@ -13,6 +13,11 @@ use super::contract::{ContractDiff, ContractMigration}; use super::world::WorldDiff; use super::MigrationType; +#[derive(Debug, Clone)] +pub enum MigrationMetadata { + Contract(ContractDiff), +} + #[derive(Debug, Clone)] pub struct MigrationStrategy { pub world_address: Option, @@ -20,6 +25,7 @@ pub struct MigrationStrategy { pub base: Option, pub contracts: Vec, pub models: Vec, + pub metadata: HashMap, } #[derive(Debug)] @@ -61,23 +67,29 @@ impl MigrationStrategy { } pub fn resolve_variable(&mut self, world_address: FieldElement) -> Result<()> { - let contracts_clone = self.contracts.clone(); for contract in self.contracts.iter_mut() { for field in contract.diff.init_calldata.iter_mut() { if let Some(dependency) = field.strip_prefix("$contract_address:") { - let dependency_contract = - contracts_clone.iter().find(|c| c.diff.name == dependency).unwrap(); - let contract_address = get_contract_address( - generate_salt(&dependency_contract.diff.name), - dependency_contract.diff.base_class_hash, - &[], - world_address, - ); - *field = contract_address.to_string(); + let dependency_contract = self.metadata.get(dependency).unwrap(); + + match dependency_contract { + MigrationMetadata::Contract(c) => { + let contract_address = get_contract_address( + generate_salt(&c.name), + c.base_class_hash, + &[], + world_address, + ); + *field = contract_address.to_string(); + } + } } else if let Some(dependency) = field.strip_prefix("$class_hash:") { - let dependency_contract = - contracts_clone.iter().find(|c| c.diff.name == dependency).unwrap(); - *field = dependency_contract.diff.local_class_hash.to_string(); + let dependency_contract = self.metadata.get(dependency).unwrap(); + match dependency_contract { + MigrationMetadata::Contract(c) => { + *field = c.local_class_hash.to_string(); + } + } } } } @@ -94,6 +106,7 @@ pub fn prepare_for_migration( target_dir: &Utf8PathBuf, diff: WorldDiff, ) -> Result { + let mut metadata = HashMap::new(); let entries = fs::read_dir(target_dir).with_context(|| { format!( "Failed trying to read target directory ({target_dir})\nNOTE: build files are profile \ @@ -122,8 +135,12 @@ pub fn prepare_for_migration( // else we need to evaluate which contracts need to be migrated. let mut world = evaluate_contract_to_migrate(&diff.world, &artifact_paths, false)?; let base = evaluate_class_to_migrate(&diff.base, &artifact_paths, world.is_some())?; - let contracts = - evaluate_contracts_to_migrate(&diff.contracts, &artifact_paths, world.is_some())?; + let contracts = evaluate_contracts_to_migrate( + &diff.contracts, + &artifact_paths, + &mut metadata, + world.is_some(), + )?; let models = evaluate_models_to_migrate(&diff.models, &artifact_paths, world.is_some())?; // If world needs to be migrated, then we expect the `seed` to be provided. @@ -151,7 +168,7 @@ pub fn prepare_for_migration( world.contract_address = generated_world_address; } - Ok(MigrationStrategy { world_address, world, base, contracts, models }) + Ok(MigrationStrategy { world_address, world, base, contracts, models, metadata }) } fn evaluate_models_to_migrate( @@ -191,11 +208,13 @@ fn evaluate_class_to_migrate( fn evaluate_contracts_to_migrate( contracts: &[ContractDiff], artifact_paths: &HashMap, + metadata: &mut HashMap, world_contract_will_migrate: bool, ) -> Result> { let mut comps_to_migrate = vec![]; for c in contracts { + metadata.insert(c.name.clone(), MigrationMetadata::Contract(c.clone())); match c.remote_class_hash { Some(remote) if remote == c.local_class_hash && !world_contract_will_migrate => { continue; diff --git a/crates/sozo/ops/src/tests/migration.rs b/crates/sozo/ops/src/tests/migration.rs index 1c070dbd48..1cc6b0b3a8 100644 --- a/crates/sozo/ops/src/tests/migration.rs +++ b/crates/sozo/ops/src/tests/migration.rs @@ -12,7 +12,7 @@ use dojo_world::metadata::{ dojo_metadata_from_workspace, ArtifactMetadata, DojoMetadata, Uri, WorldMetadata, IPFS_CLIENT_URL, IPFS_PASSWORD, IPFS_USERNAME, }; -use dojo_world::migration::strategy::prepare_for_migration; +use dojo_world::migration::strategy::{prepare_for_migration, MigrationMetadata}; use dojo_world::migration::world::WorldDiff; use dojo_world::migration::TxnConfig; use futures::TryStreamExt; @@ -91,6 +91,113 @@ async fn migrate_with_small_fee_multiplier_will_fail() { ); } +#[tokio::test] +async fn metadata_calculated_properly() { + let config = setup::load_config(); + let ws = setup::setup_ws(&config); + + let base = config.manifest_path().parent().unwrap(); + let target_dir = format!("{}/target/dev", base); + + let profile_name = ws.current_profile().unwrap().to_string(); + + let mut manifest = BaseManifest::load_from_path( + &base.to_path_buf().join(MANIFESTS_DIR).join(profile_name).join(BASE_DIR), + ) + .unwrap(); + + let overlay_manifest = + OverlayManifest::load_from_path(&base.join(MANIFESTS_DIR).join("dev").join(OVERLAYS_DIR)) + .unwrap(); + + manifest.merge(overlay_manifest); + + let world = WorldDiff::compute(manifest, None); + + let migration = prepare_for_migration( + None, + felt!("0x12345"), + &Utf8Path::new(&target_dir).to_path_buf(), + world, + ) + .unwrap(); + + // verifies that key name and actual item name are same + for (key, value) in migration.metadata.iter() { + match value { + MigrationMetadata::Contract(c) => { + assert_eq!(key, &c.name); + } + } + } +} + +#[tokio::test] +async fn migration_with_correct_calldata_second_time_work_as_expected() { + let config = setup::load_config(); + let ws = setup::setup_ws(&config); + + let base = config.manifest_path().parent().unwrap(); + let target_dir = format!("{}/target/dev", base); + + let sequencer = KatanaRunner::new().expect("Failed to start runner."); + + let account = sequencer.account(0); + + let profile_name = ws.current_profile().unwrap().to_string(); + + let mut manifest = BaseManifest::load_from_path( + &base.to_path_buf().join(MANIFESTS_DIR).join(&profile_name).join(BASE_DIR), + ) + .unwrap(); + + let world = WorldDiff::compute(manifest.clone(), None); + + let migration = prepare_for_migration( + None, + felt!("0x12345"), + &Utf8Path::new(&target_dir).to_path_buf(), + world, + ) + .unwrap(); + + let migration_output = + execute_strategy(&ws, &migration, &account, TxnConfig::init_wait()).await.unwrap(); + + // first time others will fail due to calldata error + assert!(!migration_output.full); + + let world_address = migration_output.world_address; + + let remote_manifest = DeploymentManifest::load_from_remote(sequencer.provider(), world_address) + .await + .expect("Failed to load remote manifest"); + + let overlay = OverlayManifest::load_from_path( + &base.join(MANIFESTS_DIR).join(&profile_name).join(OVERLAYS_DIR), + ) + .expect("Failed to load overlay"); + + // adding correct calldata + manifest.merge(overlay); + + let mut world = WorldDiff::compute(manifest, Some(remote_manifest)); + world.update_order().expect("Failed to update order"); + + let mut migration = prepare_for_migration( + Some(world_address), + felt!("0x12345"), + &Utf8Path::new(&target_dir).to_path_buf(), + world, + ) + .unwrap(); + migration.resolve_variable(migration.world_address().unwrap()).expect("Failed to resolve"); + + let migration_output = + execute_strategy(&ws, &migration, &account, TxnConfig::init_wait()).await.unwrap(); + assert!(migration_output.full); +} + #[tokio::test] async fn migration_from_remote() { let config = setup::load_config(); diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index 0babbac9af..bf6a5a2123 100644 --- a/crates/torii/types-test/Scarb.lock +++ b/crates/torii/types-test/Scarb.lock @@ -15,7 +15,7 @@ source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7 [[package]] name = "types_test" -version = "0.6.0" +version = "0.7.0" dependencies = [ "dojo", ] From 71e9451f856067cba19f7ff1b5da2fafa4c49677 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Mon, 17 Jun 2024 17:43:50 -0500 Subject: [PATCH 18/32] fix(ci): ensure katana runs in debian:bookworm-slim (#2073) * Ensure katana runs in debian:bookworm-slim * chore: switch to cartridge fork and adjust CI to 4 core to build Katana * chore: add old prover-sdk version to check CI fail * fix katana bin permissions * chore: add ensure-docker as requirement for big jobs * chore: point to http-prover using rustls-tls * dbg * wip * chore: bump to artifacts v4 * fix: typo * wip * fix: don't use path explicitely * wip * fix: fix artifacts managment * add ls * fix: use other path with checkout * fix: remove prints --------- Co-authored-by: glihm --- .github/workflows/ci.yml | 46 +++++++++++++++++++++++++++++-- Cargo.lock | 54 +++++-------------------------------- crates/saya/core/Cargo.toml | 2 +- 3 files changed, 51 insertions(+), 51 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 53876adc6e..c4db1a4df2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -11,16 +11,35 @@ env: RUST_VERSION: 1.76.0 jobs: + build: + runs-on: ubuntu-latest-4-cores + steps: + - uses: actions/checkout@v3 + - uses: Swatinem/rust-cache@v2 + - run: | + cargo build -r --bin katana + mkdir -p bins + cp ./target/release/katana bins/ + - uses: actions/upload-artifact@v4 + with: + name: katana-binary + path: bins + test: + needs: ensure-docker runs-on: ubuntu-latest-32-cores container: image: ghcr.io/dojoengine/dojo-dev:v0.7.0 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 + - uses: actions/download-artifact@v4 + with: + name: katana-binary + path: /tmp/bins - run: | - cargo build -r --bin katana - KATANA_RUNNER_BIN=$(pwd)/target/release/katana cargo llvm-cov nextest --no-report --all-features --workspace --exclude katana --build-jobs 20 + chmod +x /tmp/bins/katana + KATANA_RUNNER_BIN=/tmp/bins/katana cargo llvm-cov nextest --no-report --all-features --workspace --exclude katana --build-jobs 20 cargo llvm-cov nextest --no-report -p katana # TODO(kariy): uncomment this line when `sir` feature support Cairo 2.6.3 # cargo llvm-cov nextest --no-report -p katana --no-default-features --features sir @@ -40,6 +59,7 @@ jobs: - run: cargo build -r --target wasm32-unknown-unknown -p torii-client ensure-windows: + needs: ensure-docker runs-on: windows-latest steps: - uses: actions/checkout@v3 @@ -52,6 +72,28 @@ jobs: with: repo-token: ${{ secrets.github_token }} - run: cargo build --target x86_64-pc-windows-msvc --bins + + # This job is used to ensure the built katana image doesn't depend on any + # libraries that don't exist in the base docker image we use for distribution + ensure-docker: + needs: build + runs-on: ubuntu-latest + container: + image: debian:bookworm-slim + steps: + - uses: actions/download-artifact@v4 + with: + name: katana-binary + - run: | + chmod +x ./katana + ./katana & + KATANA_PID=$! + sleep 2 + if ! kill -0 $KATANA_PID; then + echo "Katana exited with an error" + exit 1 + fi + kill $KATANA_PID cairofmt: runs-on: ubuntu-latest diff --git a/Cargo.lock b/Cargo.lock index 3e5c038dd6..445ad1030e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3765,7 +3765,7 @@ dependencies = [ [[package]] name = "common" version = "0.1.0" -source = "git+https://github.com/neotheprogramist/http-prover?rev=05aa9dbb7fdd5618693cead978d4ab0eebbf8f80#05aa9dbb7fdd5618693cead978d4ab0eebbf8f80" +source = "git+https://github.com/cartridge-gg/http-prover?rev=7d00b05#7d00b05fec6bdf533d4110656c635a086d5872b7" dependencies = [ "ed25519-dalek", "prefix-hex", @@ -6500,25 +6500,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "h2" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa82e28a107a8cc405f0839610bdc9b15f1e25ec7d696aa5cf173edbcb1486ab" -dependencies = [ - "atomic-waker", - "bytes", - "fnv", - "futures-core", - "futures-sink", - "http 1.1.0", - "indexmap 2.2.6", - "slab", - "tokio", - "tokio-util", - "tracing", -] - [[package]] name = "half" version = "2.4.1" @@ -6843,7 +6824,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", "httparse", @@ -6866,7 +6847,6 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "httparse", @@ -6975,22 +6955,6 @@ dependencies = [ "tokio-native-tls", ] -[[package]] -name = "hyper-tls" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" -dependencies = [ - "bytes", - "http-body-util", - "hyper 1.3.1", - "hyper-util", - "native-tls", - "tokio", - "tokio-native-tls", - "tower-service", -] - [[package]] name = "hyper-util" version = "0.1.3" @@ -10753,7 +10717,7 @@ dependencies = [ [[package]] name = "prover-sdk" version = "0.1.0" -source = "git+https://github.com/neotheprogramist/http-prover?rev=05aa9dbb7fdd5618693cead978d4ab0eebbf8f80#05aa9dbb7fdd5618693cead978d4ab0eebbf8f80" +source = "git+https://github.com/cartridge-gg/http-prover?rev=7d00b05#7d00b05fec6bdf533d4110656c635a086d5872b7" dependencies = [ "bytes", "common 0.1.0", @@ -11129,12 +11093,12 @@ dependencies = [ "encoding_rs", "futures-core", "futures-util", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", "hyper-rustls 0.24.2", - "hyper-tls 0.5.0", + "hyper-tls", "ipnet", "js-sys", "log", @@ -11175,23 +11139,19 @@ dependencies = [ "bytes", "cookie", "cookie_store", - "encoding_rs", "futures-channel", "futures-core", "futures-util", - "h2 0.4.5", "http 1.1.0", "http-body 1.0.0", "http-body-util", "hyper 1.3.1", "hyper-rustls 0.26.0", - "hyper-tls 0.6.0", "hyper-util", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -11202,9 +11162,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", - "system-configuration", "tokio", - "tokio-native-tls", "tokio-rustls 0.25.0", "tower-service", "url", @@ -13963,7 +13921,7 @@ dependencies = [ "axum", "base64 0.21.7", "bytes", - "h2 0.3.26", + "h2", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.28", diff --git a/crates/saya/core/Cargo.toml b/crates/saya/core/Cargo.toml index 256d727638..4881647506 100644 --- a/crates/saya/core/Cargo.toml +++ b/crates/saya/core/Cargo.toml @@ -47,4 +47,4 @@ cairo-felt = "0.9.1" num-bigint = "0.4.4" num-traits = "0.2.18" -prover-sdk = { git = "https://github.com/neotheprogramist/http-prover", rev = "05aa9dbb7fdd5618693cead978d4ab0eebbf8f80" } +prover-sdk = { git = "https://github.com/cartridge-gg/http-prover", rev = "7d00b05" } From 8347ac8c8639b20c592098aa0bcc4e518d9123f1 Mon Sep 17 00:00:00 2001 From: notV4l <122404722+notV4l@users.noreply.github.com> Date: Tue, 18 Jun 2024 05:33:09 +0200 Subject: [PATCH 19/32] [dojo-core]: update gas logs (#1877) dojo-core: update gas logs Co-authored-by: glihm --- crates/dojo-core/src/benchmarks.cairo | 209 ++++++++---------- .../dojo-core/src/database/introspect.cairo | 3 - crates/dojo-core/src/test_utils.cairo | 60 ++--- crates/dojo-core/src/world_test.cairo | 25 +-- 4 files changed, 139 insertions(+), 158 deletions(-) diff --git a/crates/dojo-core/src/benchmarks.cairo b/crates/dojo-core/src/benchmarks.cairo index 2aa7482f53..b0e827ed25 100644 --- a/crates/dojo-core/src/benchmarks.cairo +++ b/crates/dojo-core/src/benchmarks.cairo @@ -10,15 +10,14 @@ use dojo::database; use dojo::database::storage; use dojo::model::Model; use dojo::world_test::Foo; -use dojo::test_utils::end; - +use dojo::test_utils::GasCounterImpl; +use dojo::database::introspect::{Introspect, Layout}; #[test] #[available_gas(1000000000)] fn bench_reference_offset() { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - end(gas, 'bench empty'); + let gas = GasCounterImpl::start(); + gas.end("bench empty"); } #[test] @@ -26,15 +25,13 @@ fn bench_reference_offset() { fn bench_storage_single() { let keys = array!['database_test', '42'].span(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); storage::set(0, keys, 420); - end(gas, 'storage set'); + gas.end("storage set"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let res = storage::get(0, keys); - end(gas, 'storage get'); + gas.end("storage get"); assert(res == 420, 'values differ'); } @@ -46,15 +43,13 @@ fn bench_storage_many() { let values = array![1, 2].span(); let layout = array![251, 251].span(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); storage::set_many(0, keys, values, 0, layout).unwrap(); - end(gas, 'storage set mny'); + gas.end("storage set_many"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let res = storage::get_many(0, keys, layout).unwrap(); - end(gas, 'storage get mny'); + gas.end("storage get_many"); assert(res.len() == 2, 'wrong number of values'); assert(*res.at(0) == *values.at(0), 'value not set'); @@ -64,22 +59,19 @@ fn bench_storage_many() { #[test] #[available_gas(1000000000)] fn bench_native_storage() { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let keys = array![0x1337].span(); let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); let address = starknet::storage_address_from_base(base); - end(gas, 'native prep'); + gas.end("native prep"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); starknet::storage_write_syscall(0, address, 42).unwrap_syscall(); - end(gas, 'native write'); + gas.end("native write"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); - end(gas, 'native read'); + gas.end("native read"); assert(value == 42, 'read invalid'); } @@ -87,22 +79,19 @@ fn bench_native_storage() { #[test] #[available_gas(1000000000)] fn bench_native_storage_offset() { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let keys = array![0x1337].span(); let base = starknet::storage_base_address_from_felt252(poseidon_hash_span(keys)); let address = starknet::storage_address_from_base_and_offset(base, 42); - end(gas, 'native prep of'); + gas.end("native prep of"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); starknet::storage_write_syscall(0, address, 42).unwrap_syscall(); - end(gas, 'native writ of'); + gas.end("native writ of"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let value = starknet::storage_read_syscall(0, address).unwrap_syscall(); - end(gas, 'native read of'); + gas.end("native read of"); assert(value == 42, 'read invalid'); } @@ -129,15 +118,13 @@ fn bench_database_array() { i += 1; }; - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); database::set('table', 'key', values.span(), 0, layout.span()); - end(gas, 'db set arr'); + gas.end("db set arr"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let res = database::get('table', 'key', layout.span()); - end(gas, 'db get arr'); + gas.end("db get arr"); let mut i = 0; loop { @@ -155,23 +142,20 @@ fn bench_database_array() { fn bench_simple_struct() { let caller = starknet::contract_address_const::<0x42>(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut foo = Foo { caller, a: 0x123456789abcdef, b: 0x123456789abcdef, }; - end(gas, 'foo init'); + gas.end("foo init"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@foo.a, ref serialized); serde::Serde::serialize(@foo.b, ref serialized); let serialized = array::ArrayTrait::span(@serialized); - end(gas, 'foo serialize'); + gas.end("foo serialize"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let values: Span = foo.values(); - end(gas, 'foo values'); + gas.end("foo values"); assert(serialized.len() == 2, 'serialized wrong length'); assert(values.len() == 2, 'value wrong length'); @@ -179,7 +163,7 @@ fn bench_simple_struct() { assert(serialized.at(1) == values.at(1), 'serialized differ at 1'); } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(Copy, Drop, Serde, IntrospectPacked)] #[dojo::model] struct PositionWithQuaterions { #[key] @@ -195,11 +179,9 @@ struct PositionWithQuaterions { // TODO: this test should be adapted to benchmark the new layout system #[test] -#[ignore] #[available_gas(1000000000)] -fn test_struct_with_many_fields() { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); +fn test_struct_with_many_fields_fixed() { + let gas = GasCounterImpl::start(); let mut pos = PositionWithQuaterions { id: 0x123456789abcdef, @@ -211,10 +193,9 @@ fn test_struct_with_many_fields() { c: 0x123456789abcdef, d: 0x123456789abcdef, }; - end(gas, 'pos init'); + gas.end("pos init"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@pos.x, ref serialized); serde::Serde::serialize(@pos.y, ref serialized); @@ -224,12 +205,11 @@ fn test_struct_with_many_fields() { serde::Serde::serialize(@pos.c, ref serialized); serde::Serde::serialize(@pos.d, ref serialized); let serialized = array::ArrayTrait::span(@serialized); - end(gas, 'pos serialize'); + gas.end("pos serialize"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let values: Span = pos.values(); - end(gas, 'pos values'); + gas.end("pos values"); assert(serialized.len() == values.len(), 'serialized not equal'); let mut idx = 0; @@ -241,26 +221,27 @@ fn test_struct_with_many_fields() { idx += 1; }; - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let layout = match dojo::model::Model::::layout() { + Layout::Fixed(layout) => layout, + _ => panic!("expected fixed layout"), + }; - //database::set('positions', '42', pos.values(), 0, pos.instance_layout()); - end(gas, 'pos db set'); + let gas = GasCounterImpl::start(); + database::set('positions', '42', pos.values(), 0, layout); + gas.end("pos db set"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - //database::get('positions', '42', pos.instance_layout()); - end(gas, 'pos db get'); + let gas = GasCounterImpl::start(); + database::get('positions', '42', layout); + gas.end("pos db get"); } - -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] struct Sword { swordsmith: ContractAddress, damage: u32, } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] #[dojo::model] struct Case { #[key] @@ -269,35 +250,33 @@ struct Case { material: felt252, } - // TODO: this test should be adapted to benchmark the new layout system #[test] #[ignore] #[available_gas(1000000000)] -fn bench_nested_struct() { +fn bench_nested_struct_packed() { let caller = starknet::contract_address_const::<0x42>(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut case = Case { owner: caller, sword: Sword { swordsmith: caller, damage: 0x12345678, }, material: 'wooden', }; - end(gas, 'case init'); + gas.end("case init"); + + // ???? let _gas = testing::get_available_gas(); gas::withdraw_gas().unwrap(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@case.sword, ref serialized); serde::Serde::serialize(@case.material, ref serialized); let serialized = array::ArrayTrait::span(@serialized); - end(gas, 'case serialize'); + gas.end("case serialize"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let values: Span = case.values(); - end(gas, 'case values'); + gas.end("case values"); assert(serialized.len() == values.len(), 'serialized not equal'); let mut idx = 0; @@ -309,19 +288,21 @@ fn bench_nested_struct() { idx += 1; }; - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let layout = match dojo::model::Model::::layout() { + Layout::Fixed(layout) => layout, + _ => panic!("expected fixed layout"), + }; - //database::set('cases', '42', values, case.instance_layout()); - end(gas, 'case db set'); + let gas = GasCounterImpl::start(); + database::set('cases', '42', values, 0, layout); + gas.end("case db set"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - //database::get('cases', '42', case.instance_layout()); - end(gas, 'case db get'); + let gas = GasCounterImpl::start(); + database::get('cases', '42', layout); + gas.end("case db get"); } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] #[dojo::model] struct Character { #[key] @@ -333,7 +314,7 @@ struct Character { gold: u32, } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] struct Abilities { strength: u8, dexterity: u8, @@ -343,7 +324,7 @@ struct Abilities { charisma: u8, } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] struct Stats { kills: u128, deaths: u16, @@ -356,7 +337,7 @@ struct Stats { romances: u16, } -#[derive(Introspect, Copy, Drop, Serde)] +#[derive(IntrospectPacked, Copy, Drop, Serde)] enum Weapon { DualWield: (Sword, Sword), Fists: (Sword, Sword), // Introspect requires same arms @@ -366,9 +347,8 @@ enum Weapon { #[test] #[ignore] #[available_gas(1000000000)] -fn bench_complex_struct() { - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); +fn bench_complex_struct_packed() { + let gas = GasCounterImpl::start(); let char = Character { caller: starknet::contract_address_const::<0x42>(), @@ -404,10 +384,9 @@ fn bench_complex_struct() { ), gold: 0x12345678, }; - end(gas, 'chars init'); + gas.end("chars init"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let mut serialized = ArrayTrait::new(); serde::Serde::serialize(@char.heigth, ref serialized); serde::Serde::serialize(@char.abilities, ref serialized); @@ -415,12 +394,11 @@ fn bench_complex_struct() { serde::Serde::serialize(@char.weapon, ref serialized); serde::Serde::serialize(@char.gold, ref serialized); let serialized = array::ArrayTrait::span(@serialized); - end(gas, 'chars serialize'); + gas.end("chars serialize"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let values: Span = char.values(); - end(gas, 'chars values'); + gas.end("chars values"); assert(serialized.len() == values.len(), 'serialized not equal'); @@ -433,13 +411,16 @@ fn bench_complex_struct() { idx += 1; }; - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - //database::set('chars', '42', char.values(), char.instance_layout()); - end(gas, 'chars db set'); + let layout = match dojo::model::Model::::layout() { + Layout::Fixed(layout) => layout, + _ => panic!("expected fixed layout"), + }; - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - //database::get('chars', '42', char.instance_layout()); - end(gas, 'chars db get'); + let gas = GasCounterImpl::start(); + database::set('chars', '42', char.values(), 0, layout); + gas.end("chars db set"); + + let gas = GasCounterImpl::start(); + database::get('chars', '42', layout); + gas.end("chars db get"); } diff --git a/crates/dojo-core/src/database/introspect.cairo b/crates/dojo-core/src/database/introspect.cairo index d3ad4e6962..1eb1e2a1ad 100644 --- a/crates/dojo-core/src/database/introspect.cairo +++ b/crates/dojo-core/src/database/introspect.cairo @@ -60,7 +60,6 @@ trait Introspect { fn ty() -> Ty; } - impl Introspect_felt252 of Introspect { fn size() -> Option { Option::Some(1) @@ -73,7 +72,6 @@ impl Introspect_felt252 of Introspect { } } - impl Introspect_bool of Introspect { fn size() -> Option { Option::Some(1) @@ -182,7 +180,6 @@ impl Introspect_classhash of Introspect { } } - impl Introspect_bytearray of Introspect { fn size() -> Option { Option::None diff --git a/crates/dojo-core/src/test_utils.cairo b/crates/dojo-core/src/test_utils.cairo index 0079e18429..1bb6c91286 100644 --- a/crates/dojo-core/src/test_utils.cairo +++ b/crates/dojo-core/src/test_utils.cairo @@ -68,36 +68,40 @@ fn spawn_test_world(models: Array) -> IWorldDispatcher { } -const GAS_OFFSET: felt252 = 0x1_000000_000000_000000_000000_000000; // 15 bajtów +#[derive(Drop)] +struct GasCounter { + start: u128, +} -/// Measures gas used after previous measurement and prints it -/// -/// # Arguments -/// -/// * `start` - gas before measurement -/// * `name` - name of test, at most 15 bytes, will be padded with spaces -fn end(start: u128, name: felt252) { - let gas_after = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); - let mut name: u256 = name.into(); - - // overwriting zeros with spaces - let mut char = 0; - loop { - if char == 15 { - break; - } - // if given byte is zero - if shl(0xff, 8 * char) & name == 0 { - name = name | shl(0x20, 8 * char); // set space - } - char += 1; - }; +#[generate_trait] +impl GasCounterImpl of GasCounterTrait { + fn start() -> GasCounter { + let start = testing::get_available_gas(); + gas::withdraw_gas().unwrap(); + GasCounter { start } + } + + fn end(self: GasCounter, name: ByteArray) { + let end = testing::get_available_gas(); + let gas_used = self.start - end; - let name: felt252 = (name % GAS_OFFSET.into()).try_into().unwrap(); - // Q?: What's this 1070 value that needed to be adjusted? - let used_gas = (start - gas_after - 1070).into() * GAS_OFFSET; - (used_gas + name).print(); + println!("# GAS # {}: {}", Self::pad_start(name, 18), gas_used); + gas::withdraw_gas().unwrap(); + } + + fn pad_start(str: ByteArray, len: u32) -> ByteArray { + let mut missing: ByteArray = ""; + let missing_len = if str.len() >= len { + 0 + } else { + len - str.len() + }; + + while missing.len() < missing_len { + missing.append(@"."); + }; + missing + str + } } // assert that `value` and `expected` have the same size and the same content diff --git a/crates/dojo-core/src/world_test.cairo b/crates/dojo-core/src/world_test.cairo index 4d8829410e..634309cd61 100644 --- a/crates/dojo-core/src/world_test.cairo +++ b/crates/dojo-core/src/world_test.cairo @@ -16,11 +16,11 @@ use dojo::world::{ use dojo::database::introspect::{Introspect, Layout, FieldLayout}; use dojo::database::MAX_ARRAY_LENGTH; use dojo::test_utils::{spawn_test_world, deploy_with_world_address, assert_array}; -use dojo::benchmarks::{Character, end}; use dojo::config::component::Config::{ DifferProgramHashUpdate, MergerProgramHashUpdate, FactsRegistryUpdate }; use dojo::model::Model; +use dojo::benchmarks::{Character, GasCounterImpl}; #[derive(Introspect, Copy, Drop, Serde)] enum OneEnum { @@ -690,15 +690,14 @@ fn bench_execute() { let alice = starknet::contract_address_const::<0x1337>(); starknet::testing::set_contract_address(alice); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); + bar_contract.set_foo(1337, 1337); - end(gas, 'foo set call'); + gas.end("foo set call"); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); let data = get!(world, alice, Foo); - end(gas, 'foo get macro'); + gas.end("foo get macro"); assert(data.a == 1337, 'data not stored'); } @@ -713,15 +712,15 @@ fn bench_execute_complex() { let alice = starknet::contract_address_const::<0x1337>(); starknet::testing::set_contract_address(alice); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); + let gas = GasCounterImpl::start(); + bar_contract.set_char(1337, 1337); - end(gas, 'char set call'); + gas.end("char set call"); + + let gas = GasCounterImpl::start(); - let gas = testing::get_available_gas(); - gas::withdraw_gas().unwrap(); let data = get!(world, alice, Character); - end(gas, 'char get macro'); + gas.end("char get macro"); assert(data.heigth == 1337, 'data not stored'); } From 36bef0f14f8e8a9afa23d9744f60cd7bbef3828d Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Mon, 17 Jun 2024 22:35:35 -0500 Subject: [PATCH 20/32] Prepare release: v0.7.1 (#2076) Co-authored-by: glihm --- Cargo.lock | 90 ++++++++++---------- Cargo.toml | 2 +- crates/dojo-core/Scarb.lock | 2 +- crates/dojo-core/Scarb.toml | 2 +- crates/katana/runner/runner-macro/Cargo.toml | 2 +- crates/torii/types-test/Scarb.lock | 2 +- crates/torii/types-test/Scarb.toml | 2 +- examples/spawn-and-move/Scarb.lock | 2 +- examples/spawn-and-move/Scarb.toml | 2 +- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 445ad1030e..62ac297394 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,7 +1338,7 @@ dependencies = [ [[package]] name = "benches" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "clap", @@ -3776,7 +3776,7 @@ dependencies = [ [[package]] name = "common" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "reqwest 0.12.4", @@ -4577,7 +4577,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dojo-bindgen" -version = "0.7.0" +version = "0.7.1" dependencies = [ "async-trait", "cainome", @@ -4595,15 +4595,15 @@ dependencies = [ [[package]] name = "dojo-core" -version = "0.7.0" +version = "0.7.1" [[package]] name = "dojo-examples-spawn-and-move" -version = "0.7.0" +version = "0.7.1" [[package]] name = "dojo-lang" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "cairo-lang-compiler 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -4654,7 +4654,7 @@ dependencies = [ [[package]] name = "dojo-language-server" -version = "0.7.0" +version = "0.7.1" dependencies = [ "cairo-lang-language-server", "clap", @@ -4663,7 +4663,7 @@ dependencies = [ [[package]] name = "dojo-metrics" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "hyper 0.14.28", @@ -4681,7 +4681,7 @@ dependencies = [ [[package]] name = "dojo-test-utils" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_fs", @@ -4715,7 +4715,7 @@ dependencies = [ [[package]] name = "dojo-types" -version = "0.7.0" +version = "0.7.1" dependencies = [ "cainome", "crypto-bigint", @@ -4731,7 +4731,7 @@ dependencies = [ [[package]] name = "dojo-world" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_fs", @@ -4770,7 +4770,7 @@ dependencies = [ [[package]] name = "dojo-world-abigen" -version = "0.7.0" +version = "0.7.1" dependencies = [ "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", "cairo-lang-starknet-classes 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7823,7 +7823,7 @@ dependencies = [ [[package]] name = "katana" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -7831,7 +7831,7 @@ dependencies = [ "cfg-if", "clap", "clap_complete", - "common 0.7.0", + "common 0.7.1", "console", "dojo-metrics", "katana-core", @@ -7850,7 +7850,7 @@ dependencies = [ [[package]] name = "katana-cairo" -version = "0.7.0" +version = "0.7.1" dependencies = [ "cairo-lang-casm 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", "cairo-lang-runner 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", @@ -7863,7 +7863,7 @@ dependencies = [ [[package]] name = "katana-codecs" -version = "0.7.0" +version = "0.7.1" dependencies = [ "bytes", "katana-primitives", @@ -7871,7 +7871,7 @@ dependencies = [ [[package]] name = "katana-codecs-derive" -version = "0.7.0" +version = "0.7.1" dependencies = [ "proc-macro2", "quote", @@ -7881,7 +7881,7 @@ dependencies = [ [[package]] name = "katana-core" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-contract", "alloy-network", @@ -7929,7 +7929,7 @@ dependencies = [ [[package]] name = "katana-db" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7951,7 +7951,7 @@ dependencies = [ [[package]] name = "katana-executor" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -7978,7 +7978,7 @@ dependencies = [ [[package]] name = "katana-primitives" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -8003,7 +8003,7 @@ dependencies = [ [[package]] name = "katana-provider" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -8029,7 +8029,7 @@ dependencies = [ [[package]] name = "katana-rpc" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_matches", @@ -8067,7 +8067,7 @@ dependencies = [ [[package]] name = "katana-rpc-api" -version = "0.7.0" +version = "0.7.1" dependencies = [ "jsonrpsee 0.16.3", "katana-core", @@ -8078,7 +8078,7 @@ dependencies = [ [[package]] name = "katana-rpc-types" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -8099,7 +8099,7 @@ dependencies = [ [[package]] name = "katana-rpc-types-builder" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "katana-executor", @@ -8111,7 +8111,7 @@ dependencies = [ [[package]] name = "katana-runner" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_fs", @@ -8130,7 +8130,7 @@ dependencies = [ [[package]] name = "katana-tasks" -version = "0.7.0" +version = "0.7.1" dependencies = [ "futures", "rayon", @@ -11503,7 +11503,7 @@ checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "runner-macro" -version = "0.7.0" +version = "0.7.1" dependencies = [ "quote", "syn 2.0.64", @@ -11771,7 +11771,7 @@ dependencies = [ [[package]] name = "saya" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "cairo-proof-parser", @@ -11792,7 +11792,7 @@ dependencies = [ [[package]] name = "saya-core" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-trait", @@ -11834,7 +11834,7 @@ dependencies = [ [[package]] name = "saya-provider" -version = "0.7.0" +version = "0.7.1" dependencies = [ "alloy-primitives", "anyhow", @@ -12006,7 +12006,7 @@ dependencies = [ [[package]] name = "scheduler" -version = "0.7.0" +version = "0.7.1" dependencies = [ "clap", "clap_complete", @@ -12642,7 +12642,7 @@ dependencies = [ [[package]] name = "sozo" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_fs", @@ -12701,7 +12701,7 @@ dependencies = [ [[package]] name = "sozo-ops" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "assert_fs", @@ -12757,7 +12757,7 @@ dependencies = [ [[package]] name = "sozo-signers" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "starknet", @@ -14028,7 +14028,7 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "torii" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-trait", @@ -14036,7 +14036,7 @@ dependencies = [ "camino", "chrono", "clap", - "common 0.7.0", + "common 0.7.1", "ctrlc", "dojo-metrics", "dojo-types", @@ -14073,7 +14073,7 @@ dependencies = [ [[package]] name = "torii-client" -version = "0.7.0" +version = "0.7.1" dependencies = [ "async-trait", "camino", @@ -14101,7 +14101,7 @@ dependencies = [ [[package]] name = "torii-core" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-trait", @@ -14140,7 +14140,7 @@ dependencies = [ [[package]] name = "torii-graphql" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-graphql", @@ -14181,7 +14181,7 @@ dependencies = [ [[package]] name = "torii-grpc" -version = "0.7.0" +version = "0.7.1" dependencies = [ "bytes", "camino", @@ -14225,7 +14225,7 @@ dependencies = [ [[package]] name = "torii-relay" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-trait", @@ -14261,7 +14261,7 @@ dependencies = [ [[package]] name = "torii-server" -version = "0.7.0" +version = "0.7.1" dependencies = [ "anyhow", "async-trait", @@ -14584,7 +14584,7 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "types-test" -version = "0.7.0" +version = "0.7.1" [[package]] name = "ucd-trie" diff --git a/Cargo.toml b/Cargo.toml index 49ea3d3980..a04570f1aa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ edition = "2021" license = "Apache-2.0" license-file = "LICENSE" repository = "https://github.com/dojoengine/dojo/" -version = "0.7.0" +version = "0.7.1" [profile.performance] codegen-units = 1 diff --git a/crates/dojo-core/Scarb.lock b/crates/dojo-core/Scarb.lock index 8f50ef208b..f084666a86 100644 --- a/crates/dojo-core/Scarb.lock +++ b/crates/dojo-core/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.0" +version = "0.7.1" dependencies = [ "dojo_plugin", ] diff --git a/crates/dojo-core/Scarb.toml b/crates/dojo-core/Scarb.toml index ddc8fb6569..9749d61ff3 100644 --- a/crates/dojo-core/Scarb.toml +++ b/crates/dojo-core/Scarb.toml @@ -2,7 +2,7 @@ cairo-version = "=2.6.3" description = "The Dojo Core library for autonomous worlds." name = "dojo" -version = "0.7.0" +version = "0.7.1" [dependencies] dojo_plugin = { git = "https://github.com/dojoengine/dojo", tag = "v0.3.11" } diff --git a/crates/katana/runner/runner-macro/Cargo.toml b/crates/katana/runner/runner-macro/Cargo.toml index 18bf78b403..97f6626b4a 100644 --- a/crates/katana/runner/runner-macro/Cargo.toml +++ b/crates/katana/runner/runner-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runner-macro" -version = "0.7.0" +version = "0.7.1" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index bf6a5a2123..d88534e849 100644 --- a/crates/torii/types-test/Scarb.lock +++ b/crates/torii/types-test/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.0" +version = "0.7.1" dependencies = [ "dojo_plugin", ] diff --git a/crates/torii/types-test/Scarb.toml b/crates/torii/types-test/Scarb.toml index 1e34e4f328..915bb556fb 100644 --- a/crates/torii/types-test/Scarb.toml +++ b/crates/torii/types-test/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "2.4.0" name = "types_test" -version = "0.7.0" +version = "0.7.1" [cairo] sierra-replace-ids = true diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 427bc2e0e4..55bf0af53d 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.0" +version = "0.7.1" dependencies = [ "dojo_plugin", ] diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index 27de8bbe1d..cace95fe62 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "=2.6.3" name = "dojo_examples" -version = "0.7.0" +version = "0.7.1" # Use the prelude with the less imports as possible # from corelib. edition = "2023_10" From c4a1feadf1d5c5ecf9593b50c1a2ca2856ae2313 Mon Sep 17 00:00:00 2001 From: glihm Date: Mon, 17 Jun 2024 22:24:07 -0600 Subject: [PATCH 21/32] fix: allow the use of self and world in an exclusive manner (#2063) * fix: allow the use of self and world in an exclusive manner * fix: fmt * fix: cairo fmt * fix: ensure a warning is emitted with generate trait and world * fix: cairo fmt --- crates/dojo-lang/src/contract.rs | 37 ++- crates/dojo-lang/src/interface.rs | 14 +- crates/dojo-lang/src/plugin.rs | 2 - crates/dojo-lang/src/plugin_test_data/system | 233 +++++++++++++----- crates/dojo-lang/src/syntax/self_param.rs | 39 +-- crates/dojo-lang/src/syntax/world_param.rs | 8 + .../dojo_examples_actions_actions.toml | 4 +- .../manifests/dev/manifest.json | 4 +- .../manifests/dev/manifest.toml | 4 +- examples/spawn-and-move/src/actions.cairo | 32 ++- 10 files changed, 259 insertions(+), 118 deletions(-) diff --git a/crates/dojo-lang/src/contract.rs b/crates/dojo-lang/src/contract.rs index c2a9c292ff..1e4e5147e0 100644 --- a/crates/dojo-lang/src/contract.rs +++ b/crates/dojo-lang/src/contract.rs @@ -4,8 +4,10 @@ use cairo_lang_defs::patcher::{PatchBuilder, RewriteNode}; use cairo_lang_defs::plugin::{ DynGeneratedFileAuxData, PluginDiagnostic, PluginGeneratedFile, PluginResult, }; +use cairo_lang_diagnostics::Severity; use cairo_lang_syntax::node::ast::MaybeModuleBody; use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::helpers::QueryAttrs; use cairo_lang_syntax::node::{ast, ids, Terminal, TypedStablePtr, TypedSyntaxNode}; use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; use dojo_types::system::Dependency; @@ -314,7 +316,7 @@ impl DojoContract { param_list: ast::ParamList, fn_diagnostic_item: ids::SyntaxStablePtrId, ) -> (String, bool) { - self_param::check_parameter(db, ¶m_list, fn_diagnostic_item, &mut self.diagnostics); + let is_self_used = self_param::check_parameter(db, ¶m_list); let world_injection = world_param::parse_world_injection( db, @@ -323,6 +325,14 @@ impl DojoContract { &mut self.diagnostics, ); + if is_self_used && world_injection != WorldParamInjectionKind::None { + self.diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: "You cannot use `self` and `world` parameters together.".to_string(), + severity: Severity::Error, + }); + } + let mut params = param_list .elements(db) .iter() @@ -340,7 +350,12 @@ impl DojoContract { .collect::>(); match world_injection { - WorldParamInjectionKind::None | WorldParamInjectionKind::View => { + WorldParamInjectionKind::None => { + if !is_self_used { + params.insert(0, "self: @ContractState".to_string()); + } + } + WorldParamInjectionKind::View => { params.insert(0, "self: @ContractState".to_string()); } WorldParamInjectionKind::External => { @@ -372,10 +387,13 @@ impl DojoContract { /// * removing `world` if present as first parameter (self excluded), /// * adding `let world = self.world_dispatcher.read();` statement at the beginning of the /// function to restore the removed `world` parameter. + /// * if `has_generate_trait` is true, the implementation containing the function has the + /// #[generate_trait] attribute. pub fn rewrite_function( &mut self, db: &dyn SyntaxGroup, fn_ast: ast::FunctionWithBody, + has_generate_trait: bool, ) -> Vec { let mut rewritten_fn = RewriteNode::from_ast(&fn_ast); @@ -385,6 +403,16 @@ impl DojoContract { fn_ast.stable_ptr().untyped(), ); + if has_generate_trait && was_world_injected { + self.diagnostics.push(PluginDiagnostic { + stable_ptr: fn_ast.stable_ptr().untyped(), + message: "You cannot use `world` and `#[generate_trait]` together. Use `self` \ + instead." + .to_string(), + severity: Severity::Error, + }); + } + // We always rewrite the params as the self parameter is added based on the // world mutability. let rewritten_params = rewritten_fn @@ -409,6 +437,9 @@ impl DojoContract { /// Rewrites all the functions of a Impl block. fn rewrite_impl(&mut self, db: &dyn SyntaxGroup, impl_ast: ast::ItemImpl) -> Vec { + let generate_attrs = impl_ast.attributes(db).query_attr(db, "generate_trait"); + let has_generate_trait = !generate_attrs.is_empty(); + if let ast::MaybeImplBody::Some(body) = impl_ast.body(db) { let body_nodes: Vec<_> = body .items(db) @@ -416,7 +447,7 @@ impl DojoContract { .iter() .flat_map(|el| { if let ast::ImplItem::Function(fn_ast) = el { - return self.rewrite_function(db, fn_ast.clone()); + return self.rewrite_function(db, fn_ast.clone(), has_generate_trait); } vec![RewriteNode::Copied(el.as_syntax_node())] }) diff --git a/crates/dojo-lang/src/interface.rs b/crates/dojo-lang/src/interface.rs index fc9bf2ef1b..1fc64b6759 100644 --- a/crates/dojo-lang/src/interface.rs +++ b/crates/dojo-lang/src/interface.rs @@ -93,7 +93,7 @@ impl DojoInterface { .map(|e| e.as_syntax_node().get_text(db)) .collect::>(); - self_param::check_parameter(db, ¶m_list, diagnostic_item, &mut self.diagnostics); + let is_self_used = self_param::check_parameter(db, ¶m_list); let world_injection = world_param::parse_world_injection( db, @@ -102,9 +102,19 @@ impl DojoInterface { &mut self.diagnostics, ); + if is_self_used && world_injection != WorldParamInjectionKind::None { + self.diagnostics.push(PluginDiagnostic { + stable_ptr: diagnostic_item, + message: "You cannot use `self` and `world` parameters together.".to_string(), + severity: Severity::Error, + }); + } + match world_injection { WorldParamInjectionKind::None => { - params.insert(0, "self: @TContractState".to_string()); + if !is_self_used { + params.insert(0, "self: @TContractState".to_string()); + } } WorldParamInjectionKind::View => { params.remove(0); diff --git a/crates/dojo-lang/src/plugin.rs b/crates/dojo-lang/src/plugin.rs index fdd7d28419..2da354fded 100644 --- a/crates/dojo-lang/src/plugin.rs +++ b/crates/dojo-lang/src/plugin.rs @@ -126,8 +126,6 @@ impl BuiltinDojoPlugin { ) -> PluginResult { PluginResult { code: None, - // All diagnostics are for now error. Severity may be moved as argument - // if warnings are required in this file. diagnostics: vec![PluginDiagnostic { stable_ptr, message, severity: Severity::Error }], remove_original_item: false, } diff --git a/crates/dojo-lang/src/plugin_test_data/system b/crates/dojo-lang/src/plugin_test_data/system index f7fbef26bb..1cc4ec33cc 100644 --- a/crates/dojo-lang/src/plugin_test_data/system +++ b/crates/dojo-lang/src/plugin_test_data/system @@ -97,12 +97,19 @@ trait INominalTrait { fn do_params_no_world(p1: felt252, p2: u8) -> felt252; fn do_params_and_world(world: @IWorldDispatcher, p2: u8) -> felt252; fn do_params_and_world_ref(ref world: IWorldDispatcher, p2: u8) -> felt252; + + fn do_with_self(self: @ContractState) -> felt252; + fn do_with_ref_self(ref self: ContractState) -> felt252; } #[dojo::interface] trait IFaultyTrait { - fn do_with_self(self: @ContractState) -> felt252; - fn do_with_ref_self(ref self: ContractState) -> felt252; + fn do_with_self_and_world(self: @ContractState, world: @IWorldDispatcher) -> felt252; + fn do_with_ref_self_and_world(ref self: ContractState, ref world: IWorldDispatcher) -> felt252; + fn do_with_self_and_world_inv(world: @IWorldDispatcher, self: @ContractState) -> felt252; + fn do_with_ref_self_and_world_inv( + ref world: IWorldDispatcher, ref self: ContractState + ) -> felt252; fn do_with_several_world_dispatchers( world: @IWorldDispatcher, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252; @@ -114,11 +121,23 @@ trait IFaultyTrait { mod MyFaultyContract { #[abi(embed_v0)] impl TestFaultyImpl of IFaultyTrait { - fn do_with_self(ref self: ContractState) -> felt252 { + fn do_with_self_and_world(self: @ContractState, world: @IWorldDispatcher) -> felt252 { 'land' } - fn do_with_ref_self(ref self: ContractState) -> felt252 { + fn do_with_ref_self_and_world( + ref self: ContractState, ref world: IWorldDispatcher + ) -> felt252 { + 'land' + } + + fn do_with_self_and_world_inv(world: @IWorldDispatcher, self: @ContractState) -> felt252 { + 'land' + } + + fn do_with_ref_self_and_world_inv( + ref world: IWorldDispatcher, ref self: ContractState + ) -> felt252 { 'land' } @@ -136,6 +155,13 @@ mod MyFaultyContract { 'land' } } + + #[generate_trait] + impl InternalImplBad of InternalUtils { + fn bad_func_using_generate(world: @IWorldDispatcher) -> felt252 { + 'land' + } + } } #[dojo::contract] @@ -170,6 +196,14 @@ mod MyNominalContract { fn do_params_and_world_ref(ref world: IWorldDispatcher, p2: u8) -> felt252 { 'land' } + + fn do_with_self(self: @ContractState) -> felt252 { + 'land' + } + + fn do_with_ref_self(ref self: ContractState) -> felt252 { + 'land' + } } #[generate_trait] @@ -326,38 +360,63 @@ error: Anything other than functions is not supported in a dojo::interface const ONE: u8; ^************^ -error: In a dojo contract or interface, you should use `world: @IWorldDispatcher` instead of `self: @ContractState`. - --> test_src/lib.cairo:98:5 - fn do_with_self(self: @ContractState) -> felt252; - ^***********************************************^ - -error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. - --> test_src/lib.cairo:99:5 - fn do_with_ref_self(ref self: ContractState) -> felt252; - ^******************************************************^ +error: World parameter must be the first parameter. + --> test_src/lib.cairo:101:5 + fn do_with_self_and_world(self: @ContractState, world: @IWorldDispatcher) -> felt252; + ^***********************************************************************************^ error: World parameter must be the first parameter. + --> test_src/lib.cairo:102:5 + fn do_with_ref_self_and_world(ref self: ContractState, ref world: IWorldDispatcher) -> felt252; + ^*********************************************************************************************^ + +error: You cannot use `self` and `world` parameters together. + --> test_src/lib.cairo:103:5 + fn do_with_self_and_world_inv(world: @IWorldDispatcher, self: @ContractState) -> felt252; + ^***************************************************************************************^ + +error: You cannot use `self` and `world` parameters together. --> test_src/lib.cairo:104:5 + fn do_with_ref_self_and_world_inv( + ^********************************^ + +error: World parameter must be the first parameter. + --> test_src/lib.cairo:111:5 fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252; ^****************************************************************************^ -error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. - --> test_src/lib.cairo:111:9 - fn do_with_self(ref self: ContractState) -> felt252 { - ^***************************************************^ +error: World parameter must be the first parameter. + --> test_src/lib.cairo:118:9 + fn do_with_self_and_world(self: @ContractState, world: @IWorldDispatcher) -> felt252 { + ^************************************************************************************^ -error: In a dojo contract or interface, you should use `ref world: IWorldDispatcher` instead of `ref self: ContractState`. - --> test_src/lib.cairo:115:9 - fn do_with_ref_self(ref self: ContractState) -> felt252 { - ^*******************************************************^ +error: World parameter must be the first parameter. + --> test_src/lib.cairo:122:9 + fn do_with_ref_self_and_world( + ^****************************^ + +error: You cannot use `self` and `world` parameters together. + --> test_src/lib.cairo:128:9 + fn do_with_self_and_world_inv(world: @IWorldDispatcher, self: @ContractState) -> felt252 { + ^****************************************************************************************^ + +error: You cannot use `self` and `world` parameters together. + --> test_src/lib.cairo:132:9 + fn do_with_ref_self_and_world_inv( + ^********************************^ error: World parameter must be the first parameter. - --> test_src/lib.cairo:129:9 + --> test_src/lib.cairo:148:9 fn do_with_world_not_first(vec: Vec2, ref world: IWorldDispatcher) -> felt252 { ^*****************************************************************************^ +error: You cannot use `world` and `#[generate_trait]` together. Use `self` instead. + --> test_src/lib.cairo:155:9 + fn bad_func_using_generate(world: @IWorldDispatcher) -> felt252 { + ^***************************************************************^ + error: World parameter must be a snapshot if `ref` is not used. - --> test_src/lib.cairo:180:5 + --> test_src/lib.cairo:214:5 fn dojo_init( ^***********^ @@ -392,22 +451,22 @@ error: Unsupported attribute. ^********^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ @@ -647,172 +706,177 @@ error: Unsupported attribute. ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:109:5 + --> test_src/lib.cairo:116:5 #[abi(embed_v0)] ^**************^ +error: Generated trait must have generic args matching the impl's generic params. + --> test_src/lib.cairo:154:29 + impl InternalImplBad of InternalUtils { + ^**************************^ + error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:107:1 + --> test_src/lib.cairo:114:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:142:5 + --> test_src/lib.cairo:168:5 #[abi(embed_v0)] ^**************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:135:1 + --> test_src/lib.cairo:161:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:178:1 + --> test_src/lib.cairo:212:1 #[dojo::contract] ^***************^ error: Unknown inline item macro: 'component'. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ error: Unsupported attribute. - --> test_src/lib.cairo:195:1 + --> test_src/lib.cairo:229:1 #[dojo::contract] ^***************^ @@ -1148,12 +1212,19 @@ impl EventDrop of core::traits::Drop::; fn do_params_and_world(self: @TContractState, p2: u8) -> felt252; fn do_params_and_world_ref(ref self: TContractState, p2: u8) -> felt252; + fn do_with_self(self: @ContractState) -> felt252; + fn do_with_ref_self(ref self: ContractState) -> felt252; + } #[starknet::interface] trait IFaultyTrait { - fn do_with_self(self: @TContractState, self: @ContractState) -> felt252; - fn do_with_ref_self(self: @TContractState, ref self: ContractState) -> felt252; + fn do_with_self_and_world(self: @ContractState, world: @IWorldDispatcher) -> felt252; + fn do_with_ref_self_and_world(ref self: ContractState, ref world: IWorldDispatcher) -> felt252; + fn do_with_self_and_world_inv(self: @TContractState, self: @ContractState) -> felt252; + fn do_with_ref_self_and_world_inv( +ref self: TContractState, ref self: ContractState + ) -> felt252; fn do_with_several_world_dispatchers( self: @TContractState, vec: Vec2, ref another_world: IWorldDispatcher ) -> felt252; @@ -1189,11 +1260,24 @@ self: @TContractState, vec: Vec2, ref another_world: IWorldDispatcher #[abi(embed_v0)] impl TestFaultyImpl of IFaultyTrait { - fn do_with_self(self: @ContractState, ref self: ContractState) -> felt252 { + fn do_with_self_and_world(self: @ContractState) -> felt252 { 'land' } - fn do_with_ref_self(self: @ContractState, ref self: ContractState) -> felt252 { + fn do_with_ref_self_and_world( + ref self: ContractState ) -> felt252 { + 'land' + } + + fn do_with_self_and_world_inv(self: @ContractState, self: @ContractState) -> felt252 { +let world = self.world_dispatcher.read(); + 'land' + } + + fn do_with_ref_self_and_world_inv( +ref self: ContractState, ref self: ContractState + ) -> felt252 { +let world = self.world_dispatcher.read(); 'land' } @@ -1213,6 +1297,14 @@ let world = self.world_dispatcher.read(); } } + #[generate_trait] + impl InternalImplBad of InternalUtils { + fn bad_func_using_generate(self: @ContractState) -> felt252 { +let world = self.world_dispatcher.read(); + 'land' + } + } + #[starknet::interface] trait IDojoInit { fn dojo_init(self: @ContractState); @@ -1237,6 +1329,9 @@ let world = self.world_dispatcher.read(); #[substorage(v0)] upgradeable: dojo::components::upgradeable::upgradeable::Storage, } + trait InternalUtils{ + fn bad_func_using_generate(self: @ContractState) -> felt252; + } impl EventDrop of core::traits::Drop::; } @@ -1300,6 +1395,14 @@ let world = self.world_dispatcher.read(); let world = self.world_dispatcher.read(); 'land' } + + fn do_with_self(self: @ContractState) -> felt252 { + 'land' + } + + fn do_with_ref_self(ref self: ContractState) -> felt252 { + 'land' + } } #[generate_trait] diff --git a/crates/dojo-lang/src/syntax/self_param.rs b/crates/dojo-lang/src/syntax/self_param.rs index 2f21ae7522..aaf3593fac 100644 --- a/crates/dojo-lang/src/syntax/self_param.rs +++ b/crates/dojo-lang/src/syntax/self_param.rs @@ -1,11 +1,9 @@ -use cairo_lang_defs::plugin::PluginDiagnostic; -use cairo_lang_diagnostics::Severity; +use cairo_lang_syntax::node::ast; use cairo_lang_syntax::node::db::SyntaxGroup; -use cairo_lang_syntax::node::{ast, ids}; use crate::syntax::utils as syntax_utils; -const SELF_PARAM_NAME: &str = "self"; +pub const SELF_PARAM_NAME: &str = "self"; /// Checks if the given function parameter is using `self` instead of `world` param. /// Adds diagnostic if that case. @@ -16,34 +14,17 @@ const SELF_PARAM_NAME: &str = "self"; /// - `param_list` - The parameter list of the function. /// - `fn_diagnostic_item` - The diagnostic item of the function. /// - `diagnostics` - The diagnostics vector. -pub fn check_parameter( - db: &dyn SyntaxGroup, - param_list: &ast::ParamList, - fn_diagnostic_item: ids::SyntaxStablePtrId, - diagnostics: &mut Vec, -) { +/// +/// # Returns +/// +/// - `true` if the function first parameter is `self`. +pub fn check_parameter(db: &dyn SyntaxGroup, param_list: &ast::ParamList) -> bool { if param_list.elements(db).is_empty() { - return; + return false; } let param_0 = param_list.elements(db)[0].clone(); - let (name, modifier, _) = syntax_utils::get_parameter_info(db, param_0.clone()); + let (name, _, _) = syntax_utils::get_parameter_info(db, param_0.clone()); - if name.eq(SELF_PARAM_NAME) { - let (expected, actual) = if modifier.eq(&"ref".to_string()) { - ("ref world: IWorldDispatcher", "ref self: ContractState") - } else { - ("world: @IWorldDispatcher", "self: @ContractState") - }; - - diagnostics.push(PluginDiagnostic { - stable_ptr: fn_diagnostic_item, - message: format!( - "In a dojo contract or interface, you should use `{}` instead of `{}`.", - expected, actual - ) - .to_string(), - severity: Severity::Error, - }); - } + name.eq(SELF_PARAM_NAME) } diff --git a/crates/dojo-lang/src/syntax/world_param.rs b/crates/dojo-lang/src/syntax/world_param.rs index aac7939770..66ef198a5e 100644 --- a/crates/dojo-lang/src/syntax/world_param.rs +++ b/crates/dojo-lang/src/syntax/world_param.rs @@ -48,6 +48,14 @@ pub fn parse_world_injection( let (name, modifiers, param_type) = syntax_utils::get_parameter_info(db, param.clone()); if !is_world_param(&name, ¶m_type) { + if name.eq(super::self_param::SELF_PARAM_NAME) && has_world_injected { + diagnostics.push(PluginDiagnostic { + stable_ptr: fn_diagnostic_item, + message: "You cannot use `self` and `world` parameters together.".to_string(), + severity: Severity::Error, + }); + } + return; } diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml index 405be86d28..f1134d5536 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" -original_class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" +class_hash = "0x54ef672addb35455d35217a62c4293f2dc681b20737716b4ef9630d759d7a96" +original_class_hash = "0x54ef672addb35455d35217a62c4293f2dc681b20737716b4ef9630d759d7a96" base_class_hash = "0x0" abi = "manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/manifest.json b/examples/spawn-and-move/manifests/dev/manifest.json index 9f2e854a95..133a1a9e54 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.json +++ b/examples/spawn-and-move/manifests/dev/manifest.json @@ -1020,8 +1020,8 @@ { "kind": "DojoContract", "address": "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af", - "class_hash": "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d", - "original_class_hash": "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d", + "class_hash": "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590", + "original_class_hash": "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590", "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", "abi": [ { diff --git a/examples/spawn-and-move/manifests/dev/manifest.toml b/examples/spawn-and-move/manifests/dev/manifest.toml index ec501b9733..71caee992c 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/manifest.toml @@ -22,8 +22,8 @@ name = "dojo::base::base" [[contracts]] kind = "DojoContract" address = "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af" -class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" -original_class_hash = "0x69ba4e0f7a03ae24f85aad88bd1a6b4eab5395474bbb6717803ffeb5aa13b8d" +class_hash = "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590" +original_class_hash = "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590" base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" abi = "manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index 143696ed80..1e9140b308 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -64,17 +64,7 @@ mod actions { // ContractState is defined by system decorator expansion fn spawn(ref world: IWorldDispatcher) { let player = get_caller_address(); - let position = get!(world, player, (Position)); - - set!( - world, - ( - Moves { player, remaining: 99, last_direction: Direction::None(()) }, - Position { - player, vec: Vec2 { x: position.vec.x + 10, y: position.vec.y + 10 } - }, - ) - ); + self.set_default_position(player, world); } fn move(ref world: IWorldDispatcher, direction: Direction) { @@ -104,6 +94,26 @@ mod actions { get!(world, player, (Position)) } } + + // The `generate_trait` attribute is not compatible with `world` parameter expansion. + // Hence, the use of `self` to access the contract state. + #[generate_trait] + impl InternalImpl of InternalUtils { + fn set_default_position( + self: @ContractState, player: ContractAddress, world: IWorldDispatcher + ) { + // The world is always accessible from `self` inside a `dojo::contract`. + // let world = self.world(); + + set!( + world, + ( + Moves { player, remaining: 99, last_direction: Direction::None }, + Position { player, vec: Vec2 { x: 10, y: 10 } }, + ) + ); + } + } } #[cfg(test)] From 7c5dd43cbb0dae159410754878f94d576747418f Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Tue, 18 Jun 2024 09:25:32 -0500 Subject: [PATCH 22/32] Update devcontainer image: v0.7.1 (#2077) Co-authored-by: glihm --- .devcontainer/devcontainer.json | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/release-dispatch.yml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b71e0f6aa2..7c2d597f16 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust { "name": "Rust", - "image": "ghcr.io/dojoengine/dojo-dev:v0.7.0", + "image": "ghcr.io/dojoengine/dojo-dev:v0.7.1", "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 16b8df0133..3754955f2e 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c4db1a4df2..ec3bb90dd8 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: needs: ensure-docker runs-on: ubuntu-latest-32-cores container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -52,7 +52,7 @@ jobs: ensure-wasm: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -109,7 +109,7 @@ jobs: dojo-core-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -118,7 +118,7 @@ jobs: dojo-spawn-and-move-example-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -127,7 +127,7 @@ jobs: dojo-world-bindings-check: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -136,7 +136,7 @@ jobs: clippy: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -145,7 +145,7 @@ jobs: fmt: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -154,7 +154,7 @@ jobs: docs: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/release-dispatch.yml b/.github/workflows/release-dispatch.yml index 6374f2428a..b857f806ec 100644 --- a/.github/workflows/release-dispatch.yml +++ b/.github/workflows/release-dispatch.yml @@ -14,7 +14,7 @@ jobs: contents: write runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.0 + image: ghcr.io/dojoengine/dojo-dev:v0.7.1 env: VERSION: "" steps: From aa926756a06c45d47e7eb0f335e19f38eea4ae74 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Tue, 18 Jun 2024 17:46:07 -0500 Subject: [PATCH 23/32] fix(torii): handle array of unknown enum variants and empty arrays (#2078) fix(torii): handle array of enums and empty arrays --- crates/dojo-types/src/schema.rs | 15 +++++---------- crates/torii/core/src/sql.rs | 5 ++++- crates/torii/graphql/src/object/entity.rs | 6 +++--- crates/torii/graphql/src/query/mod.rs | 5 +++++ 4 files changed, 17 insertions(+), 14 deletions(-) diff --git a/crates/dojo-types/src/schema.rs b/crates/dojo-types/src/schema.rs index 5b7a2615f3..fa4f2819e7 100644 --- a/crates/dojo-types/src/schema.rs +++ b/crates/dojo-types/src/schema.rs @@ -196,16 +196,11 @@ impl Ty { let arr_len: u32 = felts.remove(0).try_into().map_err(PrimitiveError::ValueOutOfRange)?; - if arr_len > 0 { - let item_ty = items_ty[0].clone(); - - items_ty.clear(); - - for _ in 0..arr_len { - let mut cur_item_ty = item_ty.clone(); - cur_item_ty.deserialize(felts)?; - items_ty.push(cur_item_ty); - } + let item_ty = items_ty.pop().unwrap(); + for _ in 0..arr_len { + let mut cur_item_ty = item_ty.clone(); + cur_item_ty.deserialize(felts)?; + items_ty.push(cur_item_ty); } } Ty::ByteArray(bytes) => { diff --git a/crates/torii/core/src/sql.rs b/crates/torii/core/src/sql.rs index 7f54ae28b6..a22963a5af 100644 --- a/crates/torii/core/src/sql.rs +++ b/crates/torii/core/src/sql.rs @@ -760,9 +760,12 @@ impl Sql { .join(", "); create_table_query.push_str(&format!( - "external_{name} TEXT CHECK(external_{name} IN ({all_options})) NOT NULL, ", + "external_{name} TEXT CHECK(external_{name} IN ({all_options})) ", )); + // if we're an array, we could have multiple enum options + create_table_query.push_str(if array_idx > 0 { ", " } else { "NOT NULL, " }); + indices.push(format!( "CREATE INDEX IF NOT EXISTS idx_{table_id}_{name} ON [{table_id}] \ (external_{name});" diff --git a/crates/torii/graphql/src/object/entity.rs b/crates/torii/graphql/src/object/entity.rs index 281f6bb356..75013b4032 100644 --- a/crates/torii/graphql/src/object/entity.rs +++ b/crates/torii/graphql/src/object/entity.rs @@ -184,7 +184,7 @@ pub async fn model_data_recursive_query( let rows = sqlx::query(&query).fetch_all(conn.as_mut()).await?; if rows.is_empty() { - return Ok(Value::Null); + return Ok(Value::List(vec![])); } let value_mapping: Value; @@ -242,9 +242,9 @@ pub async fn model_data_recursive_query( .iter() .map(|v| match v { Value::Object(map) => map.get(&Name::new("data")).unwrap().clone(), - _ => unreachable!( + ty => unreachable!( "Expected Value::Object for list \"data\" field, got {:?}", - v + ty ), }) .collect(), diff --git a/crates/torii/graphql/src/query/mod.rs b/crates/torii/graphql/src/query/mod.rs index 8a3f2f8a73..b66c37b8fd 100644 --- a/crates/torii/graphql/src/query/mod.rs +++ b/crates/torii/graphql/src/query/mod.rs @@ -94,6 +94,11 @@ fn member_to_type_data(member: &ModelMember, nested_members: &[&ModelMember]) -> if !nested_members.iter().any(|&nested_member| { nested_member.model_id == member.model_id && nested_member.id.ends_with(&member.name) + && nested_member + .id + .split('$') + .collect::>() + .starts_with(&member.id.split('$').collect::>()) }) => { TypeData::Simple(TypeRef::named("Enum")) From fc44c36cb9174645ef5a498f9e54f922370409e1 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Wed, 19 Jun 2024 00:45:44 -0500 Subject: [PATCH 24/32] refactor(torii): delete entity in all tables & array references for entity delete! (#2072) --- crates/torii/core/src/sql.rs | 52 ++++++- crates/torii/core/src/sql_test.rs | 143 +++++++++++++++++- examples/spawn-and-move/Scarb.lock | 2 +- .../dojo_examples_actions_actions.json | 7 + .../dojo_examples_actions_actions.json | 7 + .../dojo_examples_actions_actions.toml | 4 +- .../manifests/dev/manifest.json | 11 +- .../manifests/dev/manifest.toml | 4 +- examples/spawn-and-move/src/actions.cairo | 22 +++ examples/spawn-and-move/src/models.cairo | 2 +- 10 files changed, 233 insertions(+), 21 deletions(-) diff --git a/crates/torii/core/src/sql.rs b/crates/torii/core/src/sql.rs index a22963a5af..02fe9ccb21 100644 --- a/crates/torii/core/src/sql.rs +++ b/crates/torii/core/src/sql.rs @@ -696,22 +696,60 @@ impl Sql { self.query_queue .push_front(statement, vec![Argument::String(entity_id.to_string())]); for member in s.children.iter() { - if let Ty::Struct(_) = &member.ty { - let mut path_clone = path.clone(); - path_clone.push(member.name.clone()); - self.build_delete_entity_queries_recursive( - path_clone, entity_id, &member.ty, - ); - } + let mut path_clone = path.clone(); + path_clone.push(member.name.clone()); + self.build_delete_entity_queries_recursive(path_clone, entity_id, &member.ty); } } Ty::Enum(e) => { + if e.options + .iter() + .all(|o| if let Ty::Tuple(t) = &o.ty { t.is_empty() } else { false }) + { + return; + } + + let table_id = path.join("$"); + let statement = format!("DELETE FROM [{table_id}] WHERE entity_id = ?"); + self.query_queue + .push_front(statement, vec![Argument::String(entity_id.to_string())]); + for child in e.options.iter() { + if let Ty::Tuple(t) = &child.ty { + if t.is_empty() { + continue; + } + } + let mut path_clone = path.clone(); path_clone.push(child.name.clone()); self.build_delete_entity_queries_recursive(path_clone, entity_id, &child.ty); } } + Ty::Array(array) => { + let table_id = path.join("$"); + let statement = format!("DELETE FROM [{table_id}] WHERE entity_id = ?"); + self.query_queue + .push_front(statement, vec![Argument::String(entity_id.to_string())]); + + for member in array.iter() { + let mut path_clone = path.clone(); + path_clone.push("data".to_string()); + self.build_delete_entity_queries_recursive(path_clone, entity_id, member); + } + } + Ty::Tuple(t) => { + let table_id = path.join("$"); + let statement = format!("DELETE FROM [{table_id}] WHERE entity_id = ?"); + self.query_queue + .push_front(statement, vec![Argument::String(entity_id.to_string())]); + + for (idx, member) in t.iter().enumerate() { + let mut path_clone = path.clone(); + path_clone.push(format!("_{}", idx)); + self.build_delete_entity_queries_recursive(path_clone, entity_id, member); + } + } _ => {} } } diff --git a/crates/torii/core/src/sql_test.rs b/crates/torii/core/src/sql_test.rs index 09f4100caa..92d45a68e8 100644 --- a/crates/torii/core/src/sql_test.rs +++ b/crates/torii/core/src/sql_test.rs @@ -6,7 +6,7 @@ use dojo_test_utils::migration::prepare_migration; use dojo_world::contracts::world::WorldContractReader; use dojo_world::metadata::dojo_metadata_from_workspace; use dojo_world::migration::TxnConfig; -use dojo_world::utils::TransactionWaiter; +use dojo_world::utils::{TransactionExt, TransactionWaiter}; use katana_runner::KatanaRunner; use scarb::ops; use sozo_ops::migration::execute_strategy; @@ -16,11 +16,12 @@ use starknet::core::types::{BlockId, BlockTag}; use starknet::core::utils::get_selector_from_name; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::{JsonRpcClient, Provider}; -use starknet_crypto::poseidon_hash_many; +use starknet_crypto::{poseidon_hash_many, FieldElement}; use tokio::sync::broadcast; use crate::engine::{Engine, EngineConfig, Processors}; use crate::processors::register_model::RegisterModelProcessor; +use crate::processors::store_del_record::StoreDelRecordProcessor; use crate::processors::store_set_record::StoreSetRecordProcessor; use crate::sql::Sql; @@ -38,7 +39,11 @@ where db, provider, Processors { - event: vec![Box::new(RegisterModelProcessor), Box::new(StoreSetRecordProcessor)], + event: vec![ + Box::new(RegisterModelProcessor), + Box::new(StoreSetRecordProcessor), + Box::new(StoreDelRecordProcessor), + ], ..Processors::default() }, EngineConfig::default(), @@ -156,9 +161,7 @@ async fn test_load_from_remote() { assert_eq!(packed_size, 0); assert_eq!(unpacked_size, 0); - // print all entities - let entities = sqlx::query("SELECT * FROM entities").fetch_all(&pool).await.unwrap(); - assert_eq!(entities.len(), 2); + assert_eq!(count_table("entities", &pool).await, 2); let (id, keys): (String, String) = sqlx::query_as( format!( @@ -176,3 +179,131 @@ async fn test_load_from_remote() { db.execute().await.unwrap(); } + +#[tokio::test(flavor = "multi_thread")] +async fn test_load_from_remote_del() { + let options = + SqliteConnectOptions::from_str("sqlite::memory:").unwrap().create_if_missing(true); + let pool = SqlitePoolOptions::new().max_connections(5).connect_with(options).await.unwrap(); + sqlx::migrate!("../migrations").run(&pool).await.unwrap(); + + let source_project_dir = Utf8PathBuf::from("../../../examples/spawn-and-move/"); + let dojo_core_path = Utf8PathBuf::from("../../dojo-core"); + + let config = compiler::copy_tmp_config(&source_project_dir, &dojo_core_path); + let ws = scarb::ops::read_workspace(config.manifest_path(), &config).unwrap(); + let dojo_metadata = + dojo_metadata_from_workspace(&ws).expect("No current package with dojo metadata found."); + + let manifest_path = config.manifest_path(); + let base_dir = manifest_path.parent().unwrap(); + let target_dir = format!("{}/target/dev", base_dir); + + let mut migration = + prepare_migration(base_dir.into(), target_dir.into(), dojo_metadata.skip_migration) + .unwrap(); + migration.resolve_variable(migration.world_address().unwrap()).unwrap(); + + let sequencer = KatanaRunner::new().expect("Failed to start runner."); + + let provider = JsonRpcClient::new(HttpTransport::new(sequencer.url())); + + let world = WorldContractReader::new(migration.world_address().unwrap(), &provider); + + let mut account = sequencer.account(0); + account.set_block_id(BlockId::Tag(BlockTag::Pending)); + + let ws = ops::read_workspace(config.manifest_path(), &config) + .unwrap_or_else(|op| panic!("Error building workspace: {op:?}")); + + let migration_output = + execute_strategy(&ws, &migration, &account, TxnConfig::init_wait()).await.unwrap(); + + let world_address = migration_output.world_address; + + assert!(migration.world_address().unwrap() == world_address); + + // spawn + account + .execute(vec![Call { + to: migration_output + .contracts + .first() + .expect("shouldn't be empty") + .as_ref() + .expect("should be deployed") + .contract_address, + selector: get_selector_from_name("spawn").unwrap(), + calldata: vec![], + }]) + .send_with_cfg(&TxnConfig::init_wait()) + .await + .unwrap(); + + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + + // Set player config. + account + .execute(vec![Call { + to: migration_output + .contracts + .first() + .expect("shouldn't be empty") + .as_ref() + .expect("should be deployed") + .contract_address, + selector: get_selector_from_name("set_player_config").unwrap(), + // Empty ByteArray. + calldata: vec![FieldElement::ZERO, FieldElement::ZERO, FieldElement::ZERO], + }]) + .send_with_cfg(&TxnConfig::init_wait()) + .await + .unwrap(); + + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + + account + .execute(vec![Call { + to: migration_output + .contracts + .first() + .expect("shouldn't be empty") + .as_ref() + .expect("should be deployed") + .contract_address, + selector: get_selector_from_name("reset_player_config").unwrap(), + calldata: vec![], + }]) + .send_with_cfg(&TxnConfig::init_wait()) + .await + .unwrap(); + + tokio::time::sleep(tokio::time::Duration::from_secs(1)).await; + + let mut db = Sql::new(pool.clone(), world_address).await.unwrap(); + let _ = bootstrap_engine(world, db.clone(), &provider).await; + + assert_eq!(count_table("PlayerConfig", &pool).await, 0); + assert_eq!(count_table("PlayerConfig$favorite_item", &pool).await, 0); + assert_eq!(count_table("PlayerConfig$items", &pool).await, 0); + + // TODO: check how we can have a test that is more chronological with Torii re-syncing + // to ensure we can test intermediate states. + + db.execute().await.unwrap(); +} + +/// Count the number of rows in a table. +/// +/// # Arguments +/// * `table_name` - The name of the table to count the rows of. +/// * `pool` - The database pool. +/// +/// # Returns +/// The number of rows in the table. +async fn count_table(table_name: &str, pool: &sqlx::Pool) -> i64 { + let count_query = format!("SELECT COUNT(*) FROM {}", table_name); + let count: (i64,) = sqlx::query_as(&count_query).fetch_one(pool).await.unwrap(); + + count.0 +} diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 55bf0af53d..0ec4b351ac 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -10,7 +10,7 @@ dependencies = [ [[package]] name = "dojo_examples" -version = "0.7.0" +version = "0.7.1" dependencies = [ "dojo", ] diff --git a/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json index 0882f7c56d..4be28b68dd 100644 --- a/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json +++ b/examples/spawn-and-move/manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json @@ -218,6 +218,13 @@ } ], "state_mutability": "view" + }, + { + "type": "function", + "name": "reset_player_config", + "inputs": [], + "outputs": [], + "state_mutability": "external" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json index 0882f7c56d..4be28b68dd 100644 --- a/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json +++ b/examples/spawn-and-move/manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json @@ -218,6 +218,13 @@ } ], "state_mutability": "view" + }, + { + "type": "function", + "name": "reset_player_config", + "inputs": [], + "outputs": [], + "state_mutability": "external" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml index f1134d5536..b1680ae07c 100644 --- a/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml +++ b/examples/spawn-and-move/manifests/dev/base/contracts/dojo_examples_actions_actions.toml @@ -1,6 +1,6 @@ kind = "DojoContract" -class_hash = "0x54ef672addb35455d35217a62c4293f2dc681b20737716b4ef9630d759d7a96" -original_class_hash = "0x54ef672addb35455d35217a62c4293f2dc681b20737716b4ef9630d759d7a96" +class_hash = "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3" +original_class_hash = "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3" base_class_hash = "0x0" abi = "manifests/dev/abis/base/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/manifests/dev/manifest.json b/examples/spawn-and-move/manifests/dev/manifest.json index 133a1a9e54..a1a575d4aa 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.json +++ b/examples/spawn-and-move/manifests/dev/manifest.json @@ -1020,8 +1020,8 @@ { "kind": "DojoContract", "address": "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af", - "class_hash": "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590", - "original_class_hash": "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590", + "class_hash": "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3", + "original_class_hash": "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3", "base_class_hash": "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46", "abi": [ { @@ -1243,6 +1243,13 @@ } ], "state_mutability": "view" + }, + { + "type": "function", + "name": "reset_player_config", + "inputs": [], + "outputs": [], + "state_mutability": "external" } ] }, diff --git a/examples/spawn-and-move/manifests/dev/manifest.toml b/examples/spawn-and-move/manifests/dev/manifest.toml index 71caee992c..c292ce25af 100644 --- a/examples/spawn-and-move/manifests/dev/manifest.toml +++ b/examples/spawn-and-move/manifests/dev/manifest.toml @@ -22,8 +22,8 @@ name = "dojo::base::base" [[contracts]] kind = "DojoContract" address = "0x5c70a663d6b48d8e4c6aaa9572e3735a732ac3765700d470463e670587852af" -class_hash = "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590" -original_class_hash = "0x386b6b90ce188fb732305f8742885ae2fb12f120d2616d6b4d396a0fcdf3590" +class_hash = "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3" +original_class_hash = "0x3b42f80dc8ac4628b0ed6c89af9055314c0aa2192ea0d9601f262138a1e50c3" base_class_hash = "0x22f3e55b61d86c2ac5239fa3b3b8761f26b9a5c0b5f61ddbd5d756ced498b46" abi = "manifests/dev/abis/deployments/contracts/dojo_examples_actions_actions.json" reads = [] diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index 1e9140b308..6737cdea48 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -6,6 +6,7 @@ trait IActions { fn move(ref world: IWorldDispatcher, direction: Direction); fn set_player_config(ref world: IWorldDispatcher, name: ByteArray); fn get_player_position(world: @IWorldDispatcher) -> Position; + fn reset_player_config(ref world: IWorldDispatcher); } #[dojo::interface] @@ -89,6 +90,27 @@ mod actions { set!(world, (config)); } + fn reset_player_config(ref world: IWorldDispatcher) { + let player = get_caller_address(); + + let (position, moves, config) = get!(world, player, (Position, Moves, PlayerConfig)); + + delete!(world, (position, moves, config)); + + let (position, moves, config) = get!(world, player, (Position, Moves, PlayerConfig)); + + assert(moves.remaining == 0, 'bad remaining'); + assert(moves.last_direction == Direction::None, 'bad last direction'); + + assert(position.vec.x == 0, 'bad x'); + assert(position.vec.y == 0, 'bad y'); + + assert(config.items.len() == 0, 'bad items'); + assert(config.favorite_item == Option::Some(0), 'bad favorite item'); + let empty_string: ByteArray = ""; + assert(config.name == empty_string, 'bad name'); + } + fn get_player_position(world: @IWorldDispatcher) -> Position { let player = get_caller_address(); get!(world, player, (Position)) diff --git a/examples/spawn-and-move/src/models.cairo b/examples/spawn-and-move/src/models.cairo index 85cfdf1711..443c3a2e53 100644 --- a/examples/spawn-and-move/src/models.cairo +++ b/examples/spawn-and-move/src/models.cairo @@ -1,6 +1,6 @@ use starknet::ContractAddress; -#[derive(Serde, Copy, Drop, Introspect)] +#[derive(Serde, Copy, Drop, Introspect, PartialEq)] enum Direction { None, Left, From 4db8ae0c89ebbb750f75c0425e78e378363a37e0 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Wed, 19 Jun 2024 16:36:39 -0400 Subject: [PATCH 25/32] fix(katana-rpc): only include successful transactions in pending block (#2082) Only include successful transactions in pending block --- crates/katana/rpc/rpc/src/starknet.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/crates/katana/rpc/rpc/src/starknet.rs b/crates/katana/rpc/rpc/src/starknet.rs index 4bc8e544a7..603dcff366 100644 --- a/crates/katana/rpc/rpc/src/starknet.rs +++ b/crates/katana/rpc/rpc/src/starknet.rs @@ -228,10 +228,16 @@ impl StarknetApiServer for StarknetApi { sequencer_address: block_env.sequencer_address, }; + // TODO(kariy): create a method that can perform this filtering for us instead + // of doing it manually. + + // A block should only include successful transactions, we filter out the failed + // ones (didn't pass validation stage). let transactions = executor .read() .transactions() .iter() + .filter(|(_, receipt)| receipt.is_success()) .map(|(tx, _)| tx.hash) .collect::>(); @@ -307,10 +313,16 @@ impl StarknetApiServer for StarknetApi { sequencer_address: block_env.sequencer_address, }; + // TODO(kariy): create a method that can perform this filtering for us instead + // of doing it manually. + + // A block should only include successful transactions, we filter out the failed + // ones (didn't pass validation stage). let transactions = executor .read() .transactions() .iter() + .filter(|(_, receipt)| receipt.is_success()) .map(|(tx, _)| tx.clone()) .collect::>(); From 30e98034acb96545e859c22067b68eb8e281d0e8 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Wed, 19 Jun 2024 15:37:30 -0500 Subject: [PATCH 26/32] refactor(torii-core): ignore invalid txs that are included in the pending block (#2081) * refactor(torii-core): ignore invalid txs that are included in the pending block txs * fmt --- crates/torii/core/src/engine.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/crates/torii/core/src/engine.rs b/crates/torii/core/src/engine.rs index 2fb4935e6d..dcf4918c1a 100644 --- a/crates/torii/core/src/engine.rs +++ b/crates/torii/core/src/engine.rs @@ -174,12 +174,11 @@ impl Engine

{ Err(e) => { match e.to_string().as_str() { "TransactionHashNotFound" => { - warn!(target: LOG_TARGET, error = %e, transaction_hash = %format!("{:#x}", transaction.transaction_hash()), "Processing pending transaction."); - // We failed to fetch the transaction, which might be due to us indexing - // the pending transaction too fast. We will - // fail silently and retry processing the transaction in the next - // iteration. - return Ok(pending_block_tx); + // We failed to fetch the transaction, which is because + // the transaction might not have passed the validation stage. + // So we can safely ignore this transaction and not process it, as it + // rejected. + warn!(target: LOG_TARGET, transaction_hash = %format!("{:#x}", transaction.transaction_hash()), "Ignored failed pending transaction."); } _ => { error!(target: LOG_TARGET, error = %e, transaction_hash = %format!("{:#x}", transaction.transaction_hash()), "Processing pending transaction."); From 3da5cad9fdd39b81551e0668015d88262e6c5fc4 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Wed, 19 Jun 2024 22:15:48 -0500 Subject: [PATCH 27/32] Prepare release: v0.7.2 (#2090) Co-authored-by: glihm --- Cargo.lock | 90 ++++++++++---------- Cargo.toml | 2 +- crates/dojo-core/Scarb.lock | 2 +- crates/dojo-core/Scarb.toml | 2 +- crates/katana/runner/runner-macro/Cargo.toml | 2 +- crates/torii/types-test/Scarb.lock | 2 +- crates/torii/types-test/Scarb.toml | 2 +- examples/spawn-and-move/Scarb.lock | 2 +- examples/spawn-and-move/Scarb.toml | 2 +- 9 files changed, 53 insertions(+), 53 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 62ac297394..87fe8db017 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,7 +1338,7 @@ dependencies = [ [[package]] name = "benches" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "clap", @@ -3776,7 +3776,7 @@ dependencies = [ [[package]] name = "common" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "reqwest 0.12.4", @@ -4577,7 +4577,7 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dojo-bindgen" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "cainome", @@ -4595,15 +4595,15 @@ dependencies = [ [[package]] name = "dojo-core" -version = "0.7.1" +version = "0.7.2" [[package]] name = "dojo-examples-spawn-and-move" -version = "0.7.1" +version = "0.7.2" [[package]] name = "dojo-lang" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "cairo-lang-compiler 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -4654,7 +4654,7 @@ dependencies = [ [[package]] name = "dojo-language-server" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cairo-lang-language-server", "clap", @@ -4663,7 +4663,7 @@ dependencies = [ [[package]] name = "dojo-metrics" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "hyper 0.14.28", @@ -4681,7 +4681,7 @@ dependencies = [ [[package]] name = "dojo-test-utils" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_fs", @@ -4715,7 +4715,7 @@ dependencies = [ [[package]] name = "dojo-types" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cainome", "crypto-bigint", @@ -4731,7 +4731,7 @@ dependencies = [ [[package]] name = "dojo-world" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_fs", @@ -4770,7 +4770,7 @@ dependencies = [ [[package]] name = "dojo-world-abigen" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", "cairo-lang-starknet-classes 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7823,7 +7823,7 @@ dependencies = [ [[package]] name = "katana" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -7831,7 +7831,7 @@ dependencies = [ "cfg-if", "clap", "clap_complete", - "common 0.7.1", + "common 0.7.2", "console", "dojo-metrics", "katana-core", @@ -7850,7 +7850,7 @@ dependencies = [ [[package]] name = "katana-cairo" -version = "0.7.1" +version = "0.7.2" dependencies = [ "cairo-lang-casm 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", "cairo-lang-runner 2.6.3 (git+https://github.com/starkware-libs/cairo?tag=v2.6.3)", @@ -7863,7 +7863,7 @@ dependencies = [ [[package]] name = "katana-codecs" -version = "0.7.1" +version = "0.7.2" dependencies = [ "bytes", "katana-primitives", @@ -7871,7 +7871,7 @@ dependencies = [ [[package]] name = "katana-codecs-derive" -version = "0.7.1" +version = "0.7.2" dependencies = [ "proc-macro2", "quote", @@ -7881,7 +7881,7 @@ dependencies = [ [[package]] name = "katana-core" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-contract", "alloy-network", @@ -7929,7 +7929,7 @@ dependencies = [ [[package]] name = "katana-db" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "cairo-lang-starknet 2.6.3 (git+https://github.com/starkware-libs/cairo?rev=d9984ef58e2f704909e271f2f01327f520ded632)", @@ -7951,7 +7951,7 @@ dependencies = [ [[package]] name = "katana-executor" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -7978,7 +7978,7 @@ dependencies = [ [[package]] name = "katana-primitives" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -8003,7 +8003,7 @@ dependencies = [ [[package]] name = "katana-provider" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -8029,7 +8029,7 @@ dependencies = [ [[package]] name = "katana-rpc" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_matches", @@ -8067,7 +8067,7 @@ dependencies = [ [[package]] name = "katana-rpc-api" -version = "0.7.1" +version = "0.7.2" dependencies = [ "jsonrpsee 0.16.3", "katana-core", @@ -8078,7 +8078,7 @@ dependencies = [ [[package]] name = "katana-rpc-types" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -8099,7 +8099,7 @@ dependencies = [ [[package]] name = "katana-rpc-types-builder" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "katana-executor", @@ -8111,7 +8111,7 @@ dependencies = [ [[package]] name = "katana-runner" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_fs", @@ -8130,7 +8130,7 @@ dependencies = [ [[package]] name = "katana-tasks" -version = "0.7.1" +version = "0.7.2" dependencies = [ "futures", "rayon", @@ -11503,7 +11503,7 @@ checksum = "f86854cf50259291520509879a5c294c3c9a4c334e9ff65071c51e42ef1e2343" [[package]] name = "runner-macro" -version = "0.7.1" +version = "0.7.2" dependencies = [ "quote", "syn 2.0.64", @@ -11771,7 +11771,7 @@ dependencies = [ [[package]] name = "saya" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "cairo-proof-parser", @@ -11792,7 +11792,7 @@ dependencies = [ [[package]] name = "saya-core" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -11834,7 +11834,7 @@ dependencies = [ [[package]] name = "saya-provider" -version = "0.7.1" +version = "0.7.2" dependencies = [ "alloy-primitives", "anyhow", @@ -12006,7 +12006,7 @@ dependencies = [ [[package]] name = "scheduler" -version = "0.7.1" +version = "0.7.2" dependencies = [ "clap", "clap_complete", @@ -12642,7 +12642,7 @@ dependencies = [ [[package]] name = "sozo" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_fs", @@ -12701,7 +12701,7 @@ dependencies = [ [[package]] name = "sozo-ops" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "assert_fs", @@ -12757,7 +12757,7 @@ dependencies = [ [[package]] name = "sozo-signers" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "starknet", @@ -14028,7 +14028,7 @@ checksum = "ea68304e134ecd095ac6c3574494fc62b909f416c4fca77e440530221e549d3d" [[package]] name = "torii" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -14036,7 +14036,7 @@ dependencies = [ "camino", "chrono", "clap", - "common 0.7.1", + "common 0.7.2", "ctrlc", "dojo-metrics", "dojo-types", @@ -14073,7 +14073,7 @@ dependencies = [ [[package]] name = "torii-client" -version = "0.7.1" +version = "0.7.2" dependencies = [ "async-trait", "camino", @@ -14101,7 +14101,7 @@ dependencies = [ [[package]] name = "torii-core" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -14140,7 +14140,7 @@ dependencies = [ [[package]] name = "torii-graphql" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-graphql", @@ -14181,7 +14181,7 @@ dependencies = [ [[package]] name = "torii-grpc" -version = "0.7.1" +version = "0.7.2" dependencies = [ "bytes", "camino", @@ -14225,7 +14225,7 @@ dependencies = [ [[package]] name = "torii-relay" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -14261,7 +14261,7 @@ dependencies = [ [[package]] name = "torii-server" -version = "0.7.1" +version = "0.7.2" dependencies = [ "anyhow", "async-trait", @@ -14584,7 +14584,7 @@ checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "types-test" -version = "0.7.1" +version = "0.7.2" [[package]] name = "ucd-trie" diff --git a/Cargo.toml b/Cargo.toml index a04570f1aa..6bf2173cee 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ edition = "2021" license = "Apache-2.0" license-file = "LICENSE" repository = "https://github.com/dojoengine/dojo/" -version = "0.7.1" +version = "0.7.2" [profile.performance] codegen-units = 1 diff --git a/crates/dojo-core/Scarb.lock b/crates/dojo-core/Scarb.lock index f084666a86..f6e3d948fe 100644 --- a/crates/dojo-core/Scarb.lock +++ b/crates/dojo-core/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dojo_plugin", ] diff --git a/crates/dojo-core/Scarb.toml b/crates/dojo-core/Scarb.toml index 9749d61ff3..5946ebcb71 100644 --- a/crates/dojo-core/Scarb.toml +++ b/crates/dojo-core/Scarb.toml @@ -2,7 +2,7 @@ cairo-version = "=2.6.3" description = "The Dojo Core library for autonomous worlds." name = "dojo" -version = "0.7.1" +version = "0.7.2" [dependencies] dojo_plugin = { git = "https://github.com/dojoengine/dojo", tag = "v0.3.11" } diff --git a/crates/katana/runner/runner-macro/Cargo.toml b/crates/katana/runner/runner-macro/Cargo.toml index 97f6626b4a..19dab27834 100644 --- a/crates/katana/runner/runner-macro/Cargo.toml +++ b/crates/katana/runner/runner-macro/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "runner-macro" -version = "0.7.1" +version = "0.7.2" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index d88534e849..e891786546 100644 --- a/crates/torii/types-test/Scarb.lock +++ b/crates/torii/types-test/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dojo_plugin", ] diff --git a/crates/torii/types-test/Scarb.toml b/crates/torii/types-test/Scarb.toml index 915bb556fb..301b44469f 100644 --- a/crates/torii/types-test/Scarb.toml +++ b/crates/torii/types-test/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "2.4.0" name = "types_test" -version = "0.7.1" +version = "0.7.2" [cairo] sierra-replace-ids = true diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 0ec4b351ac..3fc3103280 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -3,7 +3,7 @@ version = 1 [[package]] name = "dojo" -version = "0.7.1" +version = "0.7.2" dependencies = [ "dojo_plugin", ] diff --git a/examples/spawn-and-move/Scarb.toml b/examples/spawn-and-move/Scarb.toml index cace95fe62..a122b55aca 100644 --- a/examples/spawn-and-move/Scarb.toml +++ b/examples/spawn-and-move/Scarb.toml @@ -1,7 +1,7 @@ [package] cairo-version = "=2.6.3" name = "dojo_examples" -version = "0.7.1" +version = "0.7.2" # Use the prelude with the less imports as possible # from corelib. edition = "2023_10" From 06d5803ecc2c838975ec7819f14a740360b8d379 Mon Sep 17 00:00:00 2001 From: Tarrence van As Date: Thu, 20 Jun 2024 06:45:54 -0500 Subject: [PATCH 28/32] Update devcontainer image: v0.7.2 (#2091) --- .devcontainer/devcontainer.json | 2 +- .github/workflows/bench.yml | 2 +- .github/workflows/ci.yml | 16 ++++++++-------- .github/workflows/release-dispatch.yml | 2 +- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 7c2d597f16..ec5debbc8c 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -2,7 +2,7 @@ // https://github.com/microsoft/vscode-dev-containers/tree/v0.245.2/containers/rust { "name": "Rust", - "image": "ghcr.io/dojoengine/dojo-dev:v0.7.1", + "image": "ghcr.io/dojoengine/dojo-dev:v0.7.2", "runArgs": [ "--cap-add=SYS_PTRACE", "--security-opt", diff --git a/.github/workflows/bench.yml b/.github/workflows/bench.yml index 3754955f2e..a1c2b4ffd7 100644 --- a/.github/workflows/bench.yml +++ b/.github/workflows/bench.yml @@ -14,7 +14,7 @@ jobs: build: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - run: git config --global --add safe.directory "$GITHUB_WORKSPACE" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ec3bb90dd8..a01131d856 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: needs: ensure-docker runs-on: ubuntu-latest-32-cores container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -52,7 +52,7 @@ jobs: ensure-wasm: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -109,7 +109,7 @@ jobs: dojo-core-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -118,7 +118,7 @@ jobs: dojo-spawn-and-move-example-test: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -127,7 +127,7 @@ jobs: dojo-world-bindings-check: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -136,7 +136,7 @@ jobs: clippy: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -145,7 +145,7 @@ jobs: fmt: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 @@ -154,7 +154,7 @@ jobs: docs: runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 steps: - uses: actions/checkout@v3 - uses: Swatinem/rust-cache@v2 diff --git a/.github/workflows/release-dispatch.yml b/.github/workflows/release-dispatch.yml index b857f806ec..f53e873184 100644 --- a/.github/workflows/release-dispatch.yml +++ b/.github/workflows/release-dispatch.yml @@ -14,7 +14,7 @@ jobs: contents: write runs-on: ubuntu-latest container: - image: ghcr.io/dojoengine/dojo-dev:v0.7.1 + image: ghcr.io/dojoengine/dojo-dev:v0.7.2 env: VERSION: "" steps: From 45fa7dc12ef292ef9e59a043e6be0a4248a19a12 Mon Sep 17 00:00:00 2001 From: Larko <59736843+Larkooo@users.noreply.github.com> Date: Fri, 21 Jun 2024 13:53:18 -0600 Subject: [PATCH 29/32] feat(torii-grpc): add events subscription (#2065) --- crates/torii/client/src/client/mod.rs | 29 +++- crates/torii/grpc/proto/world.proto | 11 ++ crates/torii/grpc/src/client.rs | 55 ++++++- crates/torii/grpc/src/server/mod.rs | 72 ++++++++-- .../grpc/src/server/subscriptions/event.rs | 134 ++++++++++++++++++ .../grpc/src/server/subscriptions/mod.rs | 1 + crates/torii/grpc/src/types/mod.rs | 50 +++++++ 7 files changed, 334 insertions(+), 18 deletions(-) create mode 100644 crates/torii/grpc/src/server/subscriptions/event.rs diff --git a/crates/torii/client/src/client/mod.rs b/crates/torii/client/src/client/mod.rs index a87415bb95..dead3ab1b0 100644 --- a/crates/torii/client/src/client/mod.rs +++ b/crates/torii/client/src/client/mod.rs @@ -17,10 +17,10 @@ use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::JsonRpcClient; use starknet_crypto::FieldElement; use tokio::sync::RwLock as AsyncRwLock; -use torii_grpc::client::{EntityUpdateStreaming, ModelDiffsStreaming}; -use torii_grpc::proto::world::RetrieveEntitiesResponse; -use torii_grpc::types::schema::Entity; -use torii_grpc::types::{KeysClause, Query}; +use torii_grpc::client::{EntityUpdateStreaming, EventUpdateStreaming, ModelDiffsStreaming}; +use torii_grpc::proto::world::{RetrieveEntitiesResponse, RetrieveEventsResponse}; +use torii_grpc::types::schema::{Entity, SchemaError}; +use torii_grpc::types::{Event, EventQuery, KeysClause, Query}; use torii_relay::client::EventLoop; use torii_relay::types::Message; @@ -148,6 +148,18 @@ impl Client { Ok(entities.into_iter().map(TryInto::try_into).collect::, _>>()?) } + /// Retrieve raw starknet events matching the keys provided. + /// If the keys are empty, it will return all events. + pub async fn starknet_events(&self, query: EventQuery) -> Result, Error> { + let mut grpc_client = self.inner.write().await; + let RetrieveEventsResponse { events } = grpc_client.retrieve_events(query).await?; + Ok(events + .into_iter() + .map(TryInto::try_into) + .collect::, _>>() + .map_err(SchemaError::SliceError)?) + } + /// A direct stream to grpc subscribe entities pub async fn on_entity_updated( &self, @@ -168,6 +180,15 @@ impl Client { Ok(stream) } + pub async fn on_starknet_event( + &self, + keys: Option>, + ) -> Result { + let mut grpc_client = self.inner.write().await; + let stream = grpc_client.subscribe_events(keys).await?; + Ok(stream) + } + /// Returns the value of a model. /// /// This function will only return `None`, if `model` doesn't exist. If there is no model with diff --git a/crates/torii/grpc/proto/world.proto b/crates/torii/grpc/proto/world.proto index 4bf5b181a9..7ab0c6f971 100644 --- a/crates/torii/grpc/proto/world.proto +++ b/crates/torii/grpc/proto/world.proto @@ -25,6 +25,9 @@ service World { // Retrieve events rpc RetrieveEvents (RetrieveEventsRequest) returns (RetrieveEventsResponse); + + // Subscribe to events + rpc SubscribeEvents (SubscribeEventsRequest) returns (stream SubscribeEventsResponse); } @@ -78,3 +81,11 @@ message RetrieveEventsRequest { message RetrieveEventsResponse { repeated types.Event events = 1; } + +message SubscribeEventsRequest { + types.EventKeysClause keys = 1; +} + +message SubscribeEventsResponse { + types.Event event = 1; +} diff --git a/crates/torii/grpc/src/client.rs b/crates/torii/grpc/src/client.rs index 7f34a60209..e2db66576e 100644 --- a/crates/torii/grpc/src/client.rs +++ b/crates/torii/grpc/src/client.rs @@ -6,13 +6,15 @@ use futures_util::{Stream, StreamExt, TryStreamExt}; use starknet::core::types::{FromStrError, StateDiff, StateUpdate}; use starknet_crypto::FieldElement; +use crate::proto::types::EventKeysClause; use crate::proto::world::{ world_client, MetadataRequest, RetrieveEntitiesRequest, RetrieveEntitiesResponse, - SubscribeEntitiesRequest, SubscribeEntityResponse, SubscribeModelsRequest, - SubscribeModelsResponse, + RetrieveEventsRequest, RetrieveEventsResponse, SubscribeEntitiesRequest, + SubscribeEntityResponse, SubscribeEventsRequest, SubscribeEventsResponse, + SubscribeModelsRequest, SubscribeModelsResponse, }; use crate::types::schema::{self, Entity, SchemaError}; -use crate::types::{KeysClause, Query}; +use crate::types::{Event, EventQuery, KeysClause, Query}; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -92,6 +94,14 @@ impl WorldClient { .map(|res| res.into_inner()) } + pub async fn retrieve_events( + &mut self, + query: EventQuery, + ) -> Result { + let request = RetrieveEventsRequest { query: Some(query.into()) }; + self.inner.retrieve_events(request).await.map_err(Error::Grpc).map(|res| res.into_inner()) + } + /// Subscribe to entities updates of a World. pub async fn subscribe_entities( &mut self, @@ -130,6 +140,28 @@ impl WorldClient { })))) } + /// Subscribe to the events of a World. + pub async fn subscribe_events( + &mut self, + keys: Option>, + ) -> Result { + let keys = keys.map(|keys| EventKeysClause { + keys: keys.iter().map(|key| key.to_bytes_be().to_vec()).collect(), + }); + + let stream = self + .inner + .subscribe_events(SubscribeEventsRequest { keys }) + .await + .map_err(Error::Grpc) + .map(|res| res.into_inner())?; + + Ok(EventUpdateStreaming(stream.map_ok(Box::new(|res| match res.event { + Some(event) => event.try_into().expect("must able to serialize"), + None => Event { keys: vec![], data: vec![], transaction_hash: FieldElement::ZERO }, + })))) + } + /// Subscribe to the model diff for a set of models of a World. pub async fn subscribe_model_diffs( &mut self, @@ -187,6 +219,23 @@ impl Stream for EntityUpdateStreaming { } } +type EventMappedStream = MapOk< + tonic::Streaming, + Box Event + Send>, +>; + +pub struct EventUpdateStreaming(EventMappedStream); + +impl Stream for EventUpdateStreaming { + type Item = ::Item; + fn poll_next( + mut self: std::pin::Pin<&mut Self>, + cx: &mut std::task::Context<'_>, + ) -> std::task::Poll> { + self.0.poll_next_unpin(cx) + } +} + fn empty_state_update() -> StateUpdate { StateUpdate { block_hash: FieldElement::ZERO, diff --git a/crates/torii/grpc/src/server/mod.rs b/crates/torii/grpc/src/server/mod.rs index 15db131a30..7948cc6e56 100644 --- a/crates/torii/grpc/src/server/mod.rs +++ b/crates/torii/grpc/src/server/mod.rs @@ -24,6 +24,7 @@ use starknet::core::utils::{cairo_short_string_to_felt, get_selector_from_name}; use starknet::providers::jsonrpc::HttpTransport; use starknet::providers::JsonRpcClient; use starknet_crypto::FieldElement; +use subscriptions::event::EventManager; use tokio::net::TcpListener; use tokio::sync::mpsc::Receiver; use tokio_stream::wrappers::{ReceiverStream, TcpListenerStream}; @@ -38,7 +39,9 @@ use self::subscriptions::event_message::EventMessageManager; use self::subscriptions::model_diff::{ModelDiffRequest, StateDiffManager}; use crate::proto::types::clause::ClauseType; use crate::proto::world::world_server::WorldServer; -use crate::proto::world::{SubscribeEntitiesRequest, SubscribeEntityResponse}; +use crate::proto::world::{ + SubscribeEntitiesRequest, SubscribeEntityResponse, SubscribeEventsResponse, +}; use crate::proto::{self}; use crate::types::ComparisonOperator; @@ -57,6 +60,7 @@ pub struct DojoWorld { model_cache: Arc, entity_manager: Arc, event_message_manager: Arc, + event_manager: Arc, state_diff_manager: Arc, } @@ -70,6 +74,7 @@ impl DojoWorld { let model_cache = Arc::new(ModelCache::new(pool.clone())); let entity_manager = Arc::new(EntityManager::default()); let event_message_manager = Arc::new(EventMessageManager::default()); + let event_manager = Arc::new(EventManager::default()); let state_diff_manager = Arc::new(StateDiffManager::default()); tokio::task::spawn(subscriptions::model_diff::Service::new_with_block_rcv( @@ -91,12 +96,15 @@ impl DojoWorld { Arc::clone(&model_cache), )); + tokio::task::spawn(subscriptions::event::Service::new(Arc::clone(&event_manager))); + Self { pool, world_address, model_cache, entity_manager, event_message_manager, + event_manager, state_diff_manager, } } @@ -307,7 +315,7 @@ impl DojoWorld { return Ok("%".to_string()); } Ok(FieldElement::from_byte_slice_be(bytes) - .map(|felt| format!("{:#x}", felt)) + .map(|felt| format!("{felt:#x}")) .map_err(ParseError::FromByteSliceError)?) }) .collect::, Error>>()?; @@ -392,7 +400,10 @@ impl DojoWorld { if bytes.is_empty() { return Ok("%".to_string()); } - Ok(str::from_utf8(bytes).unwrap().to_string()) + + Ok(FieldElement::from_byte_slice_be(bytes) + .map(|felt| format!("{felt:#x}")) + .map_err(ParseError::FromByteSliceError)?) }) .collect::, Error>>()?; let keys_pattern = keys.join("/") + "/%"; @@ -736,6 +747,24 @@ impl DojoWorld { Ok(RetrieveEventsResponse { events }) } + async fn subscribe_events( + &self, + clause: proto::types::EventKeysClause, + ) -> Result>, Error> { + self.event_manager + .add_subscriber( + clause + .keys + .iter() + .map(|key| { + FieldElement::from_byte_slice_be(key) + .map_err(ParseError::FromByteSliceError) + }) + .collect::, _>>()?, + ) + .await + } + fn map_row_to_entity( row: &SqliteRow, arrays_rows: &HashMap>, @@ -761,14 +790,21 @@ impl DojoWorld { } } -fn process_event_field(data: &str) -> Vec> { - data.trim_end_matches('/').split('/').map(|s| s.to_owned().into_bytes()).collect() +fn process_event_field(data: &str) -> Result>, Error> { + Ok(data + .trim_end_matches('/') + .split('/') + .map(|d| { + FieldElement::from_str(d).map_err(ParseError::FromStr).map(|f| f.to_bytes_be().to_vec()) + }) + .collect::, _>>()?) } fn map_row_to_event(row: &(String, String, String)) -> Result { - let keys = process_event_field(&row.0); - let data = process_event_field(&row.1); - let transaction_hash = row.2.to_owned().into_bytes(); + let keys = process_event_field(&row.0)?; + let data = process_event_field(&row.1)?; + let transaction_hash = + FieldElement::from_str(&row.2).map_err(ParseError::FromStr)?.to_bytes_be().to_vec(); Ok(proto::types::Event { keys, data, transaction_hash }) } @@ -778,23 +814,26 @@ type SubscribeModelsResponseStream = Pin> + Send>>; type SubscribeEntitiesResponseStream = Pin> + Send>>; +type SubscribeEventsResponseStream = + Pin> + Send>>; #[tonic::async_trait] impl proto::world::world_server::World for DojoWorld { type SubscribeModelsStream = SubscribeModelsResponseStream; type SubscribeEntitiesStream = SubscribeEntitiesResponseStream; type SubscribeEventMessagesStream = SubscribeEntitiesResponseStream; + type SubscribeEventsStream = SubscribeEventsResponseStream; async fn world_metadata( &self, _request: Request, ) -> Result, Status> { - let metadata = self.metadata().await.map_err(|e| match e { + let metadata = Some(self.metadata().await.map_err(|e| match e { Error::Sql(sqlx::Error::RowNotFound) => Status::not_found("World not found"), e => Status::internal(e.to_string()), - })?; + })?); - Ok(Response::new(MetadataResponse { metadata: Some(metadata) })) + Ok(Response::new(MetadataResponse { metadata })) } async fn subscribe_models( @@ -895,6 +934,17 @@ impl proto::world::world_server::World for DojoWorld { Ok(Response::new(events)) } + + async fn subscribe_events( + &self, + request: Request, + ) -> ServiceResult { + let keys = request.into_inner().keys.unwrap_or_default(); + + let rx = self.subscribe_events(keys).await.map_err(|e| Status::internal(e.to_string()))?; + + Ok(Response::new(Box::pin(ReceiverStream::new(rx)) as Self::SubscribeEventsStream)) + } } pub async fn new( diff --git a/crates/torii/grpc/src/server/subscriptions/event.rs b/crates/torii/grpc/src/server/subscriptions/event.rs new file mode 100644 index 0000000000..1b44ed7c23 --- /dev/null +++ b/crates/torii/grpc/src/server/subscriptions/event.rs @@ -0,0 +1,134 @@ +use std::collections::HashMap; +use std::future::Future; +use std::pin::Pin; +use std::str::FromStr; +use std::sync::Arc; +use std::task::{Context, Poll}; + +use futures::Stream; +use futures_util::StreamExt; +use rand::Rng; +use starknet_crypto::FieldElement; +use tokio::sync::mpsc::{channel, Receiver, Sender}; +use tokio::sync::RwLock; +use torii_core::error::{Error, ParseError}; +use torii_core::simple_broker::SimpleBroker; +use torii_core::sql::FELT_DELIMITER; +use torii_core::types::Event; +use tracing::{error, trace}; + +use crate::proto; +use crate::proto::world::SubscribeEventsResponse; + +pub(crate) const LOG_TARGET: &str = "torii::grpc::server::subscriptions::event"; + +pub struct EventSubscriber { + /// Event keys that the subscriber is interested in + keys: Vec, + /// The channel to send the response back to the subscriber. + sender: Sender>, +} + +#[derive(Default)] +pub struct EventManager { + subscribers: RwLock>, +} + +impl EventManager { + pub async fn add_subscriber( + &self, + keys: Vec, + ) -> Result>, Error> { + let id = rand::thread_rng().gen::(); + let (sender, receiver) = channel(1); + + // NOTE: unlock issue with firefox/safari + // initially send empty stream message to return from + // initial subscribe call + let _ = sender.send(Ok(SubscribeEventsResponse { event: None })).await; + + self.subscribers.write().await.insert(id, EventSubscriber { keys, sender }); + + Ok(receiver) + } + + pub(super) async fn remove_subscriber(&self, id: usize) { + self.subscribers.write().await.remove(&id); + } +} + +#[must_use = "Service does nothing unless polled"] +pub struct Service { + subs_manager: Arc, + simple_broker: Pin + Send>>, +} + +impl Service { + pub fn new(subs_manager: Arc) -> Self { + Self { subs_manager, simple_broker: Box::pin(SimpleBroker::::subscribe()) } + } + + async fn publish_updates(subs: Arc, event: &Event) -> Result<(), Error> { + let mut closed_stream = Vec::new(); + let keys = event + .keys + .trim_end_matches(FELT_DELIMITER) + .split(FELT_DELIMITER) + .map(FieldElement::from_str) + .collect::, _>>() + .map_err(ParseError::from)?; + let data = event + .data + .trim_end_matches(FELT_DELIMITER) + .split(FELT_DELIMITER) + .map(FieldElement::from_str) + .collect::, _>>() + .map_err(ParseError::from)?; + + for (idx, sub) in subs.subscribers.read().await.iter() { + // publish all updates if ids is empty or only ids that are subscribed to + if sub.keys.is_empty() || keys.starts_with(&sub.keys) { + let resp = proto::world::SubscribeEventsResponse { + event: Some(proto::types::Event { + keys: keys.iter().map(|k| k.to_bytes_be().to_vec()).collect(), + data: data.iter().map(|d| d.to_bytes_be().to_vec()).collect(), + transaction_hash: FieldElement::from_str(&event.transaction_hash) + .map_err(ParseError::from)? + .to_bytes_be() + .to_vec(), + }), + }; + + if sub.sender.send(Ok(resp)).await.is_err() { + closed_stream.push(*idx); + } + } + } + + for id in closed_stream { + trace!(target = LOG_TARGET, id = %id, "Closing events stream."); + subs.remove_subscriber(id).await + } + + Ok(()) + } +} + +impl Future for Service { + type Output = (); + + fn poll(self: std::pin::Pin<&mut Self>, cx: &mut Context<'_>) -> std::task::Poll { + let pin = self.get_mut(); + + while let Poll::Ready(Some(event)) = pin.simple_broker.poll_next_unpin(cx) { + let subs = Arc::clone(&pin.subs_manager); + tokio::spawn(async move { + if let Err(e) = Service::publish_updates(subs, &event).await { + error!(target = LOG_TARGET, error = %e, "Publishing events update."); + } + }); + } + + Poll::Pending + } +} diff --git a/crates/torii/grpc/src/server/subscriptions/mod.rs b/crates/torii/grpc/src/server/subscriptions/mod.rs index 821328c325..f591862bd9 100644 --- a/crates/torii/grpc/src/server/subscriptions/mod.rs +++ b/crates/torii/grpc/src/server/subscriptions/mod.rs @@ -1,4 +1,5 @@ pub mod entity; pub mod error; +pub mod event; pub mod event_message; pub mod model_diff; diff --git a/crates/torii/grpc/src/types/mod.rs b/crates/torii/grpc/src/types/mod.rs index ca39ed5510..63c108e96b 100644 --- a/crates/torii/grpc/src/types/mod.rs +++ b/crates/torii/grpc/src/types/mod.rs @@ -280,3 +280,53 @@ impl TryFrom for StateUpdate { }) } } + +#[derive(Debug, Serialize, Deserialize, PartialEq, Hash, Eq, Clone)] +pub struct Event { + pub keys: Vec, + pub data: Vec, + pub transaction_hash: FieldElement, +} + +impl TryFrom for Event { + type Error = FromByteSliceError; + + fn try_from(value: proto::types::Event) -> Result { + let keys = value + .keys + .into_iter() + .map(|k| FieldElement::from_byte_slice_be(&k)) + .collect::, _>>()?; + + let data = value + .data + .into_iter() + .map(|d| FieldElement::from_byte_slice_be(&d)) + .collect::, _>>()?; + + Ok(Self { + keys, + data, + transaction_hash: FieldElement::from_byte_slice_be(&value.transaction_hash)?, + }) + } +} + +#[derive(Debug, Serialize, Deserialize, PartialEq, Hash, Eq, Clone)] +pub struct EventQuery { + pub keys: Vec, + pub limit: u32, + pub offset: u32, +} + +impl From for proto::types::EventQuery { + fn from(value: EventQuery) -> Self { + Self { + keys: Some(proto::types::EventKeysClause { + keys: value.keys.iter().map(|k| k.to_bytes_be().into()).collect(), + }), + limit: value.limit, + offset: value.offset, + } + } +} From 4ff3bb91c0a206514025f1254120b0370bdc9328 Mon Sep 17 00:00:00 2001 From: Ammar Arif Date: Sat, 22 Jun 2024 05:30:47 +0800 Subject: [PATCH 30/32] refactor(sozo): use a wrapper type as the concrete account type (#2068) * refactor(sozo): use a wrapper type as the concrete account type commit-id:4fed8a11 * fmt * add deleted stuff * don't allow --slot.controller along with other signer * remove path requirement when giving keystore_path --------- Co-authored-by: lambda-0x <0xlambda@protonmail.com> --- Cargo.lock | 1 + bin/sozo/Cargo.toml | 1 + .../options/{account.rs => account/mod.rs} | 18 ++- bin/sozo/src/commands/options/account/type.rs | 135 ++++++++++++++++++ bin/sozo/src/commands/options/signer.rs | 2 + 5 files changed, 153 insertions(+), 4 deletions(-) rename bin/sozo/src/commands/options/{account.rs => account/mod.rs} (94%) create mode 100644 bin/sozo/src/commands/options/account/type.rs diff --git a/Cargo.lock b/Cargo.lock index 87fe8db017..6ecd7bee10 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -12665,6 +12665,7 @@ dependencies = [ "clap-verbosity-flag", "clap_complete", "console", + "derive_more", "dojo-bindgen", "dojo-lang", "dojo-test-utils", diff --git a/bin/sozo/Cargo.toml b/bin/sozo/Cargo.toml index 7c09cd7eb8..9ddf45dae6 100644 --- a/bin/sozo/Cargo.toml +++ b/bin/sozo/Cargo.toml @@ -29,6 +29,7 @@ dojo-bindgen.workspace = true dojo-lang.workspace = true dojo-types.workspace = true dojo-world = { workspace = true, features = [ "contracts", "metadata", "migration" ] } +derive_more.workspace = true futures.workspace = true hex = "0.4.3" hex-literal = "0.4.1" diff --git a/bin/sozo/src/commands/options/account.rs b/bin/sozo/src/commands/options/account/mod.rs similarity index 94% rename from bin/sozo/src/commands/options/account.rs rename to bin/sozo/src/commands/options/account/mod.rs index 6b57fa6ed1..fc71cb3f40 100644 --- a/bin/sozo/src/commands/options/account.rs +++ b/bin/sozo/src/commands/options/account/mod.rs @@ -12,6 +12,8 @@ use tracing::trace; use super::signer::SignerOptions; use super::DOJO_ACCOUNT_ADDRESS_ENV_VAR; +mod r#type; + // INVARIANT: // - For commandline: we can either specify `private_key` or `keystore_path` along with // `keystore_password`. This is enforced by Clap. @@ -24,6 +26,14 @@ pub struct AccountOptions { #[arg(global = true)] pub account_address: Option, + #[arg(global = true)] + #[arg(long = "slot.controller")] + #[arg(help_heading = "Controller options")] + #[arg(help = "Use Slot's Controller account")] + #[cfg(feature = "controller")] + #[arg(conflicts_with = "signer")] + pub controller: bool, + #[command(flatten)] #[command(next_help_heading = "Signer options")] pub signer: SignerOptions, @@ -41,7 +51,8 @@ impl AccountOptions { env_metadata: Option<&Environment>, ) -> Result> where - P: Provider + Send + Sync, + P: Provider, + P: Send + Sync, { trace!(account_options=?self, "Creating account."); let account_address = self.account_address(env_metadata)?; @@ -50,9 +61,9 @@ impl AccountOptions { let signer = self.signer.signer(env_metadata, false)?; trace!(?signer, "Signer obtained."); - let chain_id = - provider.chain_id().await.with_context(|| "Failed to retrieve network chain id.")?; + let chain_id = provider.chain_id().await.context("Failed to retrieve network chain id.")?; trace!(?chain_id); + let encoding = if self.legacy { ExecutionEncoding::Legacy } else { ExecutionEncoding::New }; trace!(?encoding, "Creating SingleOwnerAccount."); let mut account = @@ -61,7 +72,6 @@ impl AccountOptions { // The default is `Latest` in starknet-rs, which does not reflect // the nonce changes in the pending block. account.set_block_id(BlockId::Tag(BlockTag::Pending)); - Ok(account) } diff --git a/bin/sozo/src/commands/options/account/type.rs b/bin/sozo/src/commands/options/account/type.rs new file mode 100644 index 0000000000..eb388398b0 --- /dev/null +++ b/bin/sozo/src/commands/options/account/type.rs @@ -0,0 +1,135 @@ +use std::sync::Arc; + +use async_trait::async_trait; +use starknet::accounts::single_owner::SignError; +use starknet::accounts::{ + Account, Call, ConnectedAccount, Declaration, Execution, ExecutionEncoder, LegacyDeclaration, + RawDeclaration, RawExecution, RawLegacyDeclaration, SingleOwnerAccount, +}; +use starknet::core::types::contract::legacy::LegacyContractClass; +use starknet::core::types::{FieldElement, FlattenedSierraClass}; +use starknet::providers::Provider; +use starknet::signers::LocalWallet; + +#[derive(Debug, thiserror::Error)] +pub enum SozoAccountSignError { + #[error(transparent)] + Standard(#[from] SignError), +} + +/// To unify the account types, we define a wrapper type that implements the +/// [ConnectedAccount] trait and wrap the different account types. +/// +/// This is the account type that should be used by the CLI. +#[must_use] +#[non_exhaustive] +#[derive(derive_more::From)] +pub enum SozoAccount

+where + P: Send, + P: Provider, +{ + Standard(SingleOwnerAccount), +} + +#[cfg_attr(not(target_arch = "wasm32"), async_trait)] +#[cfg_attr(target_arch = "wasm32", async_trait(?Send))] +impl

Account for SozoAccount

+where + P: Provider, + P: Send + Sync, +{ + type SignError = SozoAccountSignError; + + fn address(&self) -> FieldElement { + match self { + Self::Standard(account) => account.address(), + } + } + + fn chain_id(&self) -> FieldElement { + match self { + Self::Standard(account) => account.chain_id(), + } + } + + fn declare( + &self, + contract_class: Arc, + compiled_class_hash: FieldElement, + ) -> Declaration<'_, Self> { + Declaration::new(contract_class, compiled_class_hash, self) + } + + fn declare_legacy( + &self, + contract_class: Arc, + ) -> LegacyDeclaration<'_, Self> { + LegacyDeclaration::new(contract_class, self) + } + + fn execute(&self, calls: Vec) -> Execution<'_, Self> { + Execution::new(calls, self) + } + + async fn sign_execution( + &self, + execution: &RawExecution, + query_only: bool, + ) -> Result, Self::SignError> { + let result = match self { + Self::Standard(account) => account.sign_execution(execution, query_only).await?, + }; + Ok(result) + } + + async fn sign_declaration( + &self, + declaration: &RawDeclaration, + query_only: bool, + ) -> Result, Self::SignError> { + let result = match self { + Self::Standard(account) => account.sign_declaration(declaration, query_only).await?, + }; + Ok(result) + } + + async fn sign_legacy_declaration( + &self, + declaration: &RawLegacyDeclaration, + query_only: bool, + ) -> Result, Self::SignError> { + match self { + Self::Standard(account) => { + let result = account.sign_legacy_declaration(declaration, query_only).await?; + Ok(result) + } + } + } +} + +impl

ExecutionEncoder for SozoAccount

+where + P: Provider, + P: Send + Sync, +{ + fn encode_calls(&self, calls: &[Call]) -> Vec { + match self { + Self::Standard(account) => account.encode_calls(calls), + } + } +} + +impl

ConnectedAccount for SozoAccount

+where + P: Provider, + P: Send + Sync, +{ + type Provider = P; + + fn provider(&self) -> &Self::Provider { + match self { + Self::Standard(account) => account.provider(), + } + } +} diff --git a/bin/sozo/src/commands/options/signer.rs b/bin/sozo/src/commands/options/signer.rs index 2fb9c4823b..582099eff9 100644 --- a/bin/sozo/src/commands/options/signer.rs +++ b/bin/sozo/src/commands/options/signer.rs @@ -22,6 +22,7 @@ pub struct SignerOptions { #[arg(help_heading = "Signer options - RAW")] #[arg(help = "The raw private key associated with the account contract.")] #[arg(global = true)] + #[arg(group = "signer")] pub private_key: Option, #[arg(long = "keystore", env = DOJO_KEYSTORE_PATH_ENV_VAR)] @@ -29,6 +30,7 @@ pub struct SignerOptions { #[arg(help_heading = "Signer options - KEYSTORE")] #[arg(help = "Use the keystore in the given folder or file.")] #[arg(global = true)] + #[arg(group = "signer")] pub keystore_path: Option, #[arg(long = "password", env = DOJO_KEYSTORE_PASSWORD_ENV_VAR)] From ab3306530fa3fffc005523c37582c3f49beea9f0 Mon Sep 17 00:00:00 2001 From: lambda-0x <0xlambda@protonmail.com> Date: Sat, 22 Jun 2024 07:26:22 +0530 Subject: [PATCH 31/32] fix(sozo): dev subcommand (#2080) * fix: filter out test targets * fix manifests path * return error instead of unwrap * fix: propose newer implementation to take manifests in account * fix: remove the content compare for better performances * fix: clippy * update dojo_plugin version * migrate during initial run * remove manual skipping * fix lints --------- Co-authored-by: glihm --- Cargo.lock | 4 +- bin/sozo/src/commands/build.rs | 2 +- bin/sozo/src/commands/dev.rs | 355 +++++-------------- bin/sozo/src/commands/migrate.rs | 16 + bin/sozo/src/commands/options/account/mod.rs | 2 +- bin/sozo/src/commands/options/signer.rs | 2 +- bin/sozo/src/commands/options/starknet.rs | 2 +- bin/sozo/src/commands/options/transaction.rs | 6 +- bin/sozo/src/commands/options/world.rs | 2 +- crates/dojo-core/Scarb.toml | 2 +- crates/dojo-lang/Scarb.toml | 2 +- crates/torii/types-test/Scarb.lock | 4 +- examples/spawn-and-move/.tool-versions | 2 +- examples/spawn-and-move/Scarb.lock | 4 +- 14 files changed, 122 insertions(+), 283 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6ecd7bee10..5637ea021e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10986,9 +10986,9 @@ dependencies = [ [[package]] name = "redb" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed7508e692a49b6b2290b56540384ccae9b1fb4d77065640b165835b56ffe3bb" +checksum = "a6dd20d3cdeb9c7d2366a0b16b93b35b75aec15309fbeb7ce477138c9f68c8c0" dependencies = [ "libc", ] diff --git a/bin/sozo/src/commands/build.rs b/bin/sozo/src/commands/build.rs index 5d1d5df7cf..f7384266f0 100644 --- a/bin/sozo/src/commands/build.rs +++ b/bin/sozo/src/commands/build.rs @@ -18,7 +18,7 @@ const CONTRACT_CLASS_SIZE_LABEL: &str = "Contract Class size [in bytes]\n(Sierra const CONTRACT_NAME_LABEL: &str = "Contract"; -#[derive(Debug, Args)] +#[derive(Debug, Args, Default)] pub struct BuildArgs { // Should we deprecate typescript bindings codegen? // Disabled due to lack of support in dojo.js diff --git a/bin/sozo/src/commands/dev.rs b/bin/sozo/src/commands/dev.rs index 92b20e7c66..53e7687ae8 100644 --- a/bin/sozo/src/commands/dev.rs +++ b/bin/sozo/src/commands/dev.rs @@ -1,29 +1,15 @@ -use std::mem; -use std::path::{Path, PathBuf}; use std::sync::mpsc::channel; use std::time::Duration; -use anyhow::{anyhow, Result}; -use cairo_lang_compiler::db::RootDatabase; -use cairo_lang_filesystem::db::{AsFilesGroupMut, FilesGroupEx, PrivRawFileContentQuery}; -use cairo_lang_filesystem::ids::FileId; +use anyhow::Result; use clap::Args; -use dojo_lang::scarb_internal::build_scarb_root_database; -use dojo_world::manifest::{BaseManifest, DeploymentManifest, BASE_DIR, MANIFESTS_DIR}; -use dojo_world::metadata::dojo_metadata_from_workspace; -use dojo_world::migration::world::WorldDiff; -use dojo_world::migration::TxnConfig; -use notify_debouncer_mini::notify::RecursiveMode; -use notify_debouncer_mini::{new_debouncer, DebouncedEvent, DebouncedEventKind}; -use scarb::compiler::{CairoCompilationUnit, CompilationUnit, CompilationUnitAttributes}; -use scarb::core::{Config, Workspace}; -use scarb::ops::{FeaturesOpts, FeaturesSelector}; -use sozo_ops::migration; -use starknet::accounts::ConnectedAccount; -use starknet::core::types::FieldElement; -use tracing::{error, trace}; +use notify::event::Event; +use notify::{EventKind, PollWatcher, RecursiveMode, Watcher}; +use scarb::core::Config; +use tracing::{error, info, trace}; -use super::migrate::setup_env; +use super::build::BuildArgs; +use super::migrate::MigrateArgs; use super::options::account::AccountOptions; use super::options::starknet::StarknetOptions; use super::options::world::WorldOptions; @@ -45,281 +31,114 @@ pub struct DevArgs { #[command(flatten)] pub account: AccountOptions, } + impl DevArgs { + /// Watches the `src` directory that is found at the same level of the `Scarb.toml` manifest + /// of the project into the provided [`Config`]. + /// + /// When a change is detected, it rebuilds the project and applies the migrations. pub fn run(self, config: &Config) -> Result<()> { - let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let dojo_metadata = if let Some(metadata) = dojo_metadata_from_workspace(&ws) { - metadata - } else { - return Err(anyhow!( - "No current package with dojo metadata found, dev is not yet support for \ - workspaces." - )); - }; + let (tx, rx) = channel(); - let env_metadata = if config.manifest_path().exists() { - dojo_metadata.env().cloned() - } else { - trace!("Manifest path does not exist."); - None - }; + let watcher_config = notify::Config::default().with_poll_interval(Duration::from_secs(1)); - let mut context = load_context(config)?; + let mut watcher = PollWatcher::new(tx, watcher_config)?; - let (tx, rx) = channel(); - let mut debouncer = new_debouncer(Duration::from_secs(1), None, tx)?; + let watched_directory = config.manifest_path().parent().unwrap().join("src"); - debouncer.watcher().watch( - config.manifest_path().parent().unwrap().as_std_path(), - RecursiveMode::Recursive, - )?; + watcher.watch(watched_directory.as_std_path(), RecursiveMode::Recursive).unwrap(); - let name = self.name.unwrap_or_else(|| ws.current_package().unwrap().id.name.to_string()); + // Always build the project before starting the dev loop to make sure that the project is + // in a valid state. Devs may not use `build` anymore when using `dev`. + BuildArgs::default().run(config)?; + info!("Initial build completed."); - let mut previous_manifest: Option = Option::None; - let result = build(&mut context); + let _ = MigrateArgs::new_apply( + self.name.clone(), + self.world.clone(), + self.starknet.clone(), + self.account.clone(), + ) + .run(config); - let Some((mut world_address, account, _)) = context - .ws - .config() - .tokio_handle() - .block_on(setup_env( - &context.ws, - self.account, - self.starknet, - self.world, - &name, - env_metadata.as_ref(), - )) - .ok() - else { - return Err(anyhow!("Failed to setup environment.")); - }; + info!( + directory = watched_directory.to_string(), + "Initial migration completed. Waiting for changes." + ); + + let mut e_handler = EventHandler; - match context.ws.config().tokio_handle().block_on(migrate( - world_address, - &account, - &name, - &context.ws, - previous_manifest.clone(), - dojo_metadata.skip_migration.clone(), - )) { - Ok((manifest, address)) => { - previous_manifest = Some(manifest); - world_address = address; - } - Err(error) => { - error!( - error = ?error, - address = ?world_address, - "Migrating world." - ); - } - } loop { - let action = match rx.recv() { - Ok(Ok(events)) => events - .iter() - .map(|event| process_event(event, &mut context)) - .last() - .unwrap_or(DevAction::None), - Ok(Err(_)) => DevAction::None, + let is_rebuild_needed = match rx.recv() { + Ok(maybe_event) => match maybe_event { + Ok(event) => e_handler.process_event(event), + Err(error) => { + error!(?error, "Processing event."); + break; + } + }, Err(error) => { - error!(error = ?error, "Receiving dev action."); + error!(?error, "Receiving event."); break; } }; - if action != DevAction::None && build(&mut context).is_ok() { - match context.ws.config().tokio_handle().block_on(migrate( - world_address, - &account, - &name, - &context.ws, - previous_manifest.clone(), - dojo_metadata.skip_migration.clone(), - )) { - Ok((manifest, address)) => { - previous_manifest = Some(manifest); - world_address = address; - } - Err(error) => { - error!( - error = ?error, - address = ?world_address, - "Migrating world.", - ); - } - } - } - } - result - } -} - -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -enum DevAction { - None, - Reload, - Build(PathBuf), -} - -fn handle_event(event: &DebouncedEvent) -> DevAction { - let action = match event.kind { - DebouncedEventKind::Any => { - let p = event.path.clone(); - if let Some(filename) = p.file_name() { - if filename == "Scarb.toml" { - return DevAction::Reload; - } else if let Some(extension) = p.extension() { - if extension == "cairo" { - return DevAction::Build(p.clone()); - } - } + if is_rebuild_needed { + // Ignore the fails of those commands as the `run` function + // already logs the error. + let _ = BuildArgs::default().run(config); + + let _ = MigrateArgs::new_apply( + self.name.clone(), + self.world.clone(), + self.starknet.clone(), + self.account.clone(), + ) + .run(config); } - DevAction::None } - _ => DevAction::None, - }; - trace!(?action, "Determined action."); - action -} - -struct DevContext<'a> { - pub db: RootDatabase, - pub unit: CairoCompilationUnit, - pub ws: Workspace<'a>, -} - -fn load_context(config: &Config) -> Result> { - let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; - let packages: Vec = ws.members().map(|p| p.id).collect(); - let resolve = scarb::ops::resolve_workspace(&ws)?; - - let features_opts = - FeaturesOpts { features: FeaturesSelector::AllFeatures, no_default_features: false }; - - let compilation_units = scarb::ops::generate_compilation_units(&resolve, &features_opts, &ws)? - .into_iter() - .filter(|cu| packages.contains(&cu.main_package_id())) - .collect::>(); - - // we have only 1 unit in projects - // TODO: double check if we always have one with the new version and the order if many. - trace!(unit_count = compilation_units.len(), "Gathering compilation units."); - if let CompilationUnit::Cairo(unit) = compilation_units.first().unwrap() { - let db = build_scarb_root_database(unit).unwrap(); - Ok(DevContext { db, unit: unit.clone(), ws }) - } else { - Err(anyhow!("Cairo Compilation Unit is expected at this point.")) + Ok(()) } } -fn build(context: &mut DevContext<'_>) -> Result<()> { - let ws = &context.ws; - let unit = &context.unit; - let package_name = unit.main_package_id.name.clone(); - ws.config().compilers().compile(unit.clone(), &mut (context.db), ws).map_err(|err| { - ws.config().ui().anyhow(&err); +#[derive(Debug, Default)] +struct EventHandler; - anyhow!("could not compile `{package_name}` due to previous error") - })?; - ws.config().ui().print("📦 Rebuild done"); - Ok(()) -} - -// TODO: fix me -async fn migrate( - mut world_address: Option, - account: A, - name: &str, - ws: &Workspace<'_>, - previous_manifest: Option, - skip_migration: Option>, -) -> Result<(DeploymentManifest, Option)> -where - A: ConnectedAccount + Sync + Send, - A::Provider: Send, - A::SignError: 'static, -{ - let target_dir = ws.target_dir().path_existent().unwrap(); - let target_dir = target_dir.join(ws.config().profile().as_str()); +impl EventHandler { + /// Processes a debounced event and return true if a rebuild is needed. + /// Only considers Cairo file and the Scarb.toml manifest. + fn process_event(&mut self, event: Event) -> bool { + trace!(?event, "Processing event."); - // `parent` returns `None` only when its root path, so its safe to unwrap - let manifest_dir = ws.manifest_path().parent().unwrap().to_path_buf(); - - if !manifest_dir.join(MANIFESTS_DIR).exists() { - return Err(anyhow!("Build project using `sozo build` first")); - } - - let mut new_manifest = - BaseManifest::load_from_path(&manifest_dir.join(MANIFESTS_DIR).join(BASE_DIR))?; - - if let Some(skip_manifests) = skip_migration { - new_manifest.remove_items(skip_manifests); - } - - let diff = WorldDiff::compute(new_manifest.clone(), previous_manifest); - let total_diffs = diff.count_diffs(); - let config = ws.config(); - config.ui().print(format!("Total diffs found: {total_diffs}")); - if total_diffs == 0 { - return Ok((new_manifest.into(), world_address)); - } - - let ui = ws.config().ui(); - let mut strategy = migration::prepare_migration(&target_dir, diff, name, world_address, &ui)?; + let paths = match event.kind { + EventKind::Modify(_) => event.paths, + EventKind::Remove(_) => event.paths, + EventKind::Create(_) => event.paths, + _ => vec![], + }; - match migration::apply_diff(ws, account, TxnConfig::default(), &mut strategy).await { - Ok(migration_output) => { - config.ui().print(format!( - "🎉 World at address {} updated!", - format_args!("{:#x}", migration_output.world_address) - )); - world_address = Some(migration_output.world_address); + if paths.is_empty() { + return false; } - Err(err) => { - config.ui().error(err.to_string()); - return Err(err); - } - } - Ok((new_manifest.into(), world_address)) -} + let mut is_rebuild_needed = false; -fn process_event(event: &DebouncedEvent, context: &mut DevContext<'_>) -> DevAction { - trace!(event=?event, "Processing event."); - let action = handle_event(event); - match &action { - DevAction::None => {} - DevAction::Build(path) => handle_build_action(path, context), - DevAction::Reload => { - handle_reload_action(context); + for path in &paths { + if let Some(filename) = path.file_name() { + if filename == "Scarb.toml" { + info!("Rebuild to include Scarb.toml changes."); + is_rebuild_needed = true; + } else if let Some(extension) = path.extension() { + if extension == "cairo" { + let file = path.to_string_lossy().to_string(); + info!(file, "Rebuild from Cairo file change."); + is_rebuild_needed = true; + } + } + } } - } - - trace!(action=?action, "Processed action."); - action -} -fn handle_build_action(path: &Path, context: &mut DevContext<'_>) { - context - .ws - .config() - .ui() - .print(format!("📦 Need to rebuild {}", path.to_str().unwrap_or_default(),)); - let db = &mut context.db; - let file = FileId::new(db, path.to_path_buf()); - PrivRawFileContentQuery.in_db_mut(db.as_files_group_mut()).invalidate(&file); - db.override_file_content(file, None); -} - -fn handle_reload_action(context: &mut DevContext<'_>) { - trace!("Reloading context."); - let config = context.ws.config(); - config.ui().print("Reloading project"); - let new_context = load_context(config).expect("Failed to load context"); - let _ = mem::replace(context, new_context); - trace!("Context reloaded."); + is_rebuild_needed + } } diff --git a/bin/sozo/src/commands/migrate.rs b/bin/sozo/src/commands/migrate.rs index 239a78f58d..02a8bf46aa 100644 --- a/bin/sozo/src/commands/migrate.rs +++ b/bin/sozo/src/commands/migrate.rs @@ -55,6 +55,22 @@ pub enum MigrateCommand { } impl MigrateArgs { + /// Creates a new `MigrateArgs` with the `Apply` command. + pub fn new_apply( + name: Option, + world: WorldOptions, + starknet: StarknetOptions, + account: AccountOptions, + ) -> Self { + Self { + command: MigrateCommand::Apply { transaction: TransactionOptions::init_wait() }, + name, + world, + starknet, + account, + } + } + pub fn run(self, config: &Config) -> Result<()> { trace!(args = ?self); let ws = scarb::ops::read_workspace(config.manifest_path(), config)?; diff --git a/bin/sozo/src/commands/options/account/mod.rs b/bin/sozo/src/commands/options/account/mod.rs index fc71cb3f40..eba8d53d63 100644 --- a/bin/sozo/src/commands/options/account/mod.rs +++ b/bin/sozo/src/commands/options/account/mod.rs @@ -19,7 +19,7 @@ mod r#type; // `keystore_password`. This is enforced by Clap. // - For `Scarb.toml`: if both private_key and keystore are specified in `Scarb.toml` private_key // will take priority -#[derive(Debug, Args)] +#[derive(Debug, Args, Clone)] #[command(next_help_heading = "Account options")] pub struct AccountOptions { #[arg(long, env = DOJO_ACCOUNT_ADDRESS_ENV_VAR)] diff --git a/bin/sozo/src/commands/options/signer.rs b/bin/sozo/src/commands/options/signer.rs index 582099eff9..04b59b913b 100644 --- a/bin/sozo/src/commands/options/signer.rs +++ b/bin/sozo/src/commands/options/signer.rs @@ -9,7 +9,7 @@ use tracing::trace; use super::{DOJO_KEYSTORE_PASSWORD_ENV_VAR, DOJO_KEYSTORE_PATH_ENV_VAR, DOJO_PRIVATE_KEY_ENV_VAR}; -#[derive(Debug, Args)] +#[derive(Debug, Args, Clone)] #[command(next_help_heading = "Signer options")] // INVARIANT: // - For commandline: we can either specify `private_key` or `keystore_path` along with diff --git a/bin/sozo/src/commands/options/starknet.rs b/bin/sozo/src/commands/options/starknet.rs index 5b14de281d..186d7ea242 100644 --- a/bin/sozo/src/commands/options/starknet.rs +++ b/bin/sozo/src/commands/options/starknet.rs @@ -8,7 +8,7 @@ use url::Url; use super::STARKNET_RPC_URL_ENV_VAR; -#[derive(Debug, Args)] +#[derive(Debug, Args, Clone)] #[command(next_help_heading = "Starknet options")] pub struct StarknetOptions { #[arg(long, env = STARKNET_RPC_URL_ENV_VAR)] diff --git a/bin/sozo/src/commands/options/transaction.rs b/bin/sozo/src/commands/options/transaction.rs index ddd028e117..f3fb1d9534 100644 --- a/bin/sozo/src/commands/options/transaction.rs +++ b/bin/sozo/src/commands/options/transaction.rs @@ -4,7 +4,7 @@ use dojo_world::migration::{TxnAction, TxnConfig}; use starknet::core::types::FieldElement; use tracing::trace; -#[derive(Debug, Args)] +#[derive(Debug, Args, Default)] #[command(next_help_heading = "Transaction options")] pub struct TransactionOptions { #[arg(long, value_name = "MULTIPLIER")] @@ -40,6 +40,10 @@ pub struct TransactionOptions { } impl TransactionOptions { + pub fn init_wait() -> Self { + TransactionOptions { wait: true, ..Default::default() } + } + pub fn to_txn_action(&self, simulate: bool, estimate_only: bool) -> Result { match (estimate_only, simulate) { (true, true) => { diff --git a/bin/sozo/src/commands/options/world.rs b/bin/sozo/src/commands/options/world.rs index 7cd4584355..88f1bbd5f2 100644 --- a/bin/sozo/src/commands/options/world.rs +++ b/bin/sozo/src/commands/options/world.rs @@ -8,7 +8,7 @@ use tracing::trace; use super::DOJO_WORLD_ADDRESS_ENV_VAR; -#[derive(Debug, Args)] +#[derive(Debug, Args, Clone)] #[command(next_help_heading = "World options")] pub struct WorldOptions { #[arg(help = "The address of the World contract.")] diff --git a/crates/dojo-core/Scarb.toml b/crates/dojo-core/Scarb.toml index 5946ebcb71..98a8f89e3f 100644 --- a/crates/dojo-core/Scarb.toml +++ b/crates/dojo-core/Scarb.toml @@ -5,5 +5,5 @@ name = "dojo" version = "0.7.2" [dependencies] -dojo_plugin = { git = "https://github.com/dojoengine/dojo", tag = "v0.3.11" } +dojo_plugin = { git = "https://github.com/dojoengine/dojo", tag = "v0.7.2" } starknet = "=2.6.3" diff --git a/crates/dojo-lang/Scarb.toml b/crates/dojo-lang/Scarb.toml index a533c510d2..8431e93375 100644 --- a/crates/dojo-lang/Scarb.toml +++ b/crates/dojo-lang/Scarb.toml @@ -1,5 +1,5 @@ [package] name = "dojo_plugin" -version = "0.4.1" +version = "0.7.2" [cairo-plugin] diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index e891786546..fbf70e2be2 100644 --- a/crates/torii/types-test/Scarb.lock +++ b/crates/torii/types-test/Scarb.lock @@ -10,8 +10,8 @@ dependencies = [ [[package]] name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7d8aa29a92062fcb9e6659" +version = "0.4.1" +source = "git+https://github.com/dojoengine/dojo?tag=v0.7.2#3da5cad9fdd39b81551e0668015d88262e6c5fc4" [[package]] name = "types_test" diff --git a/examples/spawn-and-move/.tool-versions b/examples/spawn-and-move/.tool-versions index 21cfc80772..f239fe235a 100644 --- a/examples/spawn-and-move/.tool-versions +++ b/examples/spawn-and-move/.tool-versions @@ -1 +1 @@ -scarb 2.4.0 +scarb 2.6.3 diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index 3fc3103280..e9a0b90f18 100644 --- a/examples/spawn-and-move/Scarb.lock +++ b/examples/spawn-and-move/Scarb.lock @@ -17,5 +17,5 @@ dependencies = [ [[package]] name = "dojo_plugin" -version = "0.3.11" -source = "git+https://github.com/dojoengine/dojo?tag=v0.3.11#1e651b5d4d3b79b14a7d8aa29a92062fcb9e6659" +version = "0.4.1" +source = "git+https://github.com/dojoengine/dojo?tag=v0.7.2#3da5cad9fdd39b81551e0668015d88262e6c5fc4" From 0d3c0b0d5a36e36e003ce8ef066054d54a3c4041 Mon Sep 17 00:00:00 2001 From: Neo <128649481+neotheprogramist@users.noreply.github.com> Date: Sat, 22 Jun 2024 03:59:15 +0200 Subject: [PATCH 32/32] [saya] Publish proof to Celestia (#2053) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * updated celestia and publishing proof * specifying whether to include proof blob * fix: cleanup --------- Co-authored-by: Mateusz Zając Co-authored-by: glihm --- Cargo.lock | 29 +++++++++++++------ bin/saya/src/args/data_availability.rs | 5 ++++ bin/saya/src/args/mod.rs | 5 ++++ bin/saya/src/args/test_saya_config_file.json | 1 + crates/saya/core/Cargo.toml | 4 +-- .../src/data_availability/celestia/mod.rs | 22 ++++++++++++-- crates/saya/core/src/data_availability/mod.rs | 15 ++++++++++ crates/saya/core/src/lib.rs | 29 ++++++++++++++----- 8 files changed, 89 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5637ea021e..5c48da049b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1576,11 +1576,10 @@ dependencies = [ [[package]] name = "blockstore" -version = "0.1.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5bff157a9c999bf0a39ca45e0b62076aa27135012cfbf9cc54ad1cf971876f0" +checksum = "358358b19add120a5afc3dd1c8e9161d6d06c44dfec2ef8da58b7fe5c369c90d" dependencies = [ - "async-trait", "cid", "dashmap", "multihash 0.19.1", @@ -3425,9 +3424,9 @@ dependencies = [ [[package]] name = "celestia-proto" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d93904482a787d8caecb3a348788704fa044df6fb2402f28da5b91a2a5eabb" +checksum = "7f22a6baf972f7277acfd5c4ff9b894df7db5b0aaecdb57b9b77b5679fff323e" dependencies = [ "anyhow", "celestia-tendermint-proto", @@ -3439,9 +3438,9 @@ dependencies = [ [[package]] name = "celestia-rpc" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f4c948ab3cd9562d256b752d874d573c836ec8b200bba87d1154bbf662d3a00" +checksum = "c891b0371a6ae5a37650f1806221185cad25a1e19a11031707b6239ac720f0df" dependencies = [ "async-trait", "celestia-types", @@ -3501,9 +3500,9 @@ dependencies = [ [[package]] name = "celestia-types" -version = "0.1.1" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc3c4c6698257125b315c04236a28cf5156a866211d336ba6ac70cc5f88e24eb" +checksum = "e20dce9a482131ec8a3c69c2cbe9b57bd838b26757952094e35397acb170b427" dependencies = [ "base64 0.21.7", "bech32", @@ -3515,6 +3514,7 @@ dependencies = [ "cid", "const_format", "enum_dispatch", + "leopard-codec", "libp2p-identity", "multiaddr 0.18.1", "multihash 0.19.1", @@ -8269,6 +8269,17 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" +[[package]] +name = "leopard-codec" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee58dbc414bd23885d7da915e0457618b36d1fc950a6169ef2cb29829d1b1a1d" +dependencies = [ + "bytes", + "lazy_static", + "thiserror", +] + [[package]] name = "libc" version = "0.2.154" diff --git a/bin/saya/src/args/data_availability.rs b/bin/saya/src/args/data_availability.rs index ba5ca4dd38..8b7e406b0e 100644 --- a/bin/saya/src/args/data_availability.rs +++ b/bin/saya/src/args/data_availability.rs @@ -43,6 +43,11 @@ pub struct CelestiaOptions { #[arg(help = "The namespace used to submit blobs.")] #[arg(requires = "celestia_node_url")] pub celestia_namespace: Option, + + #[arg(long)] + #[arg(help = "Whether to include a proof to the publish DA.")] + #[arg(default_value_t = false)] + pub skip_publishing_proof: bool, } // -- Clap enums impls -- diff --git a/bin/saya/src/args/mod.rs b/bin/saya/src/args/mod.rs index 7c40bd4935..f0a257d6e4 100644 --- a/bin/saya/src/args/mod.rs +++ b/bin/saya/src/args/mod.rs @@ -97,6 +97,8 @@ impl TryFrom for SayaConfig { type Error = Box; fn try_from(args: SayaArgs) -> Result { + let skip_publishing_proof = args.data_availability.celestia.skip_publishing_proof; + if let Some(config_file) = args.config_file { let file = File::open(config_file).map_err(|_| "Failed to open config file")?; let reader = BufReader::new(file); @@ -147,6 +149,7 @@ impl TryFrom for SayaConfig { data_availability: da_config, world_address: args.proof.world_address, fact_registry_address: args.proof.fact_registry_address, + skip_publishing_proof, }) } } @@ -181,6 +184,7 @@ mod tests { celestia_node_url: None, celestia_node_auth_token: None, celestia_namespace: None, + skip_publishing_proof: true, }, }, proof: ProofOptions { @@ -199,6 +203,7 @@ mod tests { "0xd0fa91f4949e9a777ebec071ca3ca6acc1f5cd6c6827f123b798f94e73425027" ); assert!(!config.store_proofs); + assert!(config.skip_publishing_proof); assert_eq!(config.start_block, 0); if let Some(DataAvailabilityConfig::Celestia(celestia_config)) = config.data_availability { assert_eq!(celestia_config.node_url.as_str(), "http://localhost:26657/"); diff --git a/bin/saya/src/args/test_saya_config_file.json b/bin/saya/src/args/test_saya_config_file.json index 478f88faf6..ba73f97434 100644 --- a/bin/saya/src/args/test_saya_config_file.json +++ b/bin/saya/src/args/test_saya_config_file.json @@ -7,6 +7,7 @@ "world_address": "0x332b8ff41b1b026991fa9b7f0ec352909f8bc33416b65a80527edc988a9b082", "fact_registry_address": "0x217746a5f74c2e5b6fa92c97e902d8cd78b1fabf1e8081c4aa0d2fe159bc0eb", "start_block": 0, + "skip_publishing_proof": true, "data_availability": { "Celestia": { "node_url": "http://localhost:26657", diff --git a/crates/saya/core/Cargo.toml b/crates/saya/core/Cargo.toml index 4881647506..b44ecbeabc 100644 --- a/crates/saya/core/Cargo.toml +++ b/crates/saya/core/Cargo.toml @@ -40,8 +40,8 @@ tracing.workspace = true url.workspace = true # TODO: use features for each possible DA. -celestia-rpc = "0.1.1" -celestia-types = "0.1.1" +celestia-rpc = "0.2.0" +celestia-types = "0.2.0" cairo-felt = "0.9.1" num-bigint = "0.4.4" diff --git a/crates/saya/core/src/data_availability/celestia/mod.rs b/crates/saya/core/src/data_availability/celestia/mod.rs index 17bbed633c..7e85dd1567 100644 --- a/crates/saya/core/src/data_availability/celestia/mod.rs +++ b/crates/saya/core/src/data_availability/celestia/mod.rs @@ -3,7 +3,7 @@ use std::fmt::Display; use async_trait::async_trait; use celestia_rpc::{BlobClient, Client}; -use celestia_types::blob::SubmitOptions; +use celestia_types::blob::GasPrice; use celestia_types::nmt::Namespace; use celestia_types::Blob; use serde::{Deserialize, Serialize}; @@ -65,7 +65,25 @@ impl DataAvailabilityClient for CelestiaClient { // TODO: we may want to use `blob_get` to ensure the state diff has been published // correctly. self.client - .blob_submit(&[blob], SubmitOptions::default()) + .blob_submit(&[blob], GasPrice::default()) + .await + .map_err(|e| Error::Client(format!("Celestia RPC error: {e}"))) + } + + async fn publish_state_diff_and_proof_felts( + &self, + state_diff: &[FieldElement], + state_diff_proof: &[FieldElement], + ) -> DataAvailabilityResult { + let bytes: Vec = state_diff.iter().flat_map(|fe| fe.to_bytes_be().to_vec()).collect(); + let blob = Blob::new(self.namespace, bytes)?; + + let proof_bytes: Vec = + state_diff_proof.iter().flat_map(|fe| fe.to_bytes_be().to_vec()).collect(); + let proof_blob = Blob::new(self.namespace, proof_bytes)?; + + self.client + .blob_submit(&[blob, proof_blob], GasPrice::default()) .await .map_err(|e| Error::Client(format!("Celestia RPC error: {e}"))) } diff --git a/crates/saya/core/src/data_availability/mod.rs b/crates/saya/core/src/data_availability/mod.rs index 8bfe270cc6..d5ae1d410b 100644 --- a/crates/saya/core/src/data_availability/mod.rs +++ b/crates/saya/core/src/data_availability/mod.rs @@ -61,6 +61,21 @@ pub trait DataAvailabilityClient { &self, state_diff: &[FieldElement], ) -> DataAvailabilityResult; + + /// Publishes both data and transition proof on the DA layer atomically. + /// Returns the block height in which the state diff was included. + /// + /// # Arguments + /// + /// * `state_diff` - An array of felt representing the data to be published on the DA layer. We + /// use felt as all fields inside the state diff can be expressed as a felt. Nonce and updates + /// count are limited to 64 bits anyway. + /// * `state_diff_proof` - The serialized transition proof corresponding to the `state_diff`. + async fn publish_state_diff_and_proof_felts( + &self, + state_diff: &[FieldElement], + state_diff_proof: &[FieldElement], + ) -> DataAvailabilityResult; } /// Initializes a [`DataAvailabilityClient`] from a [`DataAvailabilityConfig`]. diff --git a/crates/saya/core/src/lib.rs b/crates/saya/core/src/lib.rs index f3c98ef1de..60e4f891bd 100644 --- a/crates/saya/core/src/lib.rs +++ b/crates/saya/core/src/lib.rs @@ -53,6 +53,7 @@ pub struct SayaConfig { pub data_availability: Option, pub world_address: FieldElement, pub fact_registry_address: FieldElement, + pub skip_publishing_proof: bool, } fn url_deserializer<'de, D>(deserializer: D) -> Result @@ -190,7 +191,9 @@ impl Saya { let mut state_updates_and_exec_info = vec![]; - let (state_updates, da_state_updates): (Vec<_>, Vec<_>) = future::try_join_all( + // The serialized DA is not used here as we only need the state updates to generate the + // proof and the DA data are generated by the `dojo-os`. + let (state_updates, _): (Vec<_>, Vec<_>) = future::try_join_all( block_numbers .clone() .map(|block_number| self.provider.fetch_state_updates(block_number)), @@ -205,13 +208,6 @@ impl Saya { ) .await?; - for da_state_update in da_state_updates { - if let Some(da) = &self.da_client { - // Publish state difference if DA client is available - da.publish_state_diff_felts(&da_state_update).await?; - } - } - state_updates.into_iter().zip(transactions_executions.into_iter()).for_each( |(state_updates, exec_info)| { state_updates_and_exec_info.push((state_updates, exec_info)); @@ -326,6 +322,8 @@ impl Saya { let (proof, state_diff, (_, last_block)) = prove_scheduler.proved().await.context("Failed to prove.")?; + trace!(target: LOG_TARGET, last_block, "Processing proven blocks."); + if self.config.store_proofs { let filename = format!("proof_{}.json", last_block); let mut file = File::create(filename).await.context("Failed to create proof file.")?; @@ -335,6 +333,17 @@ impl Saya { let serialized_proof: Vec = parse(&proof)?.into(); let world_da = state_diff.world_da.unwrap(); + // Publish state difference if DA client is available + if let Some(da) = &self.da_client { + trace!(target: LOG_TARGET, last_block, "Publishing DA."); + + if self.config.skip_publishing_proof { + da.publish_state_diff_felts(&world_da).await?; + } else { + da.publish_state_diff_and_proof_felts(&world_da, &serialized_proof).await?; + } + } + trace!(target: LOG_TARGET, last_block, "Verifying block."); let (transaction_hash, nonce_after) = verifier::verify( VerifierIdentifier::HerodotusStarknetSepolia(self.config.fact_registry_address), @@ -348,6 +357,10 @@ impl Saya { let expected_fact = poseidon_hash_many(&[program_hash, program_output_hash]).to_string(); info!(target: LOG_TARGET, expected_fact, "Expected fact."); + // When not waiting for couple of second `apply_diffs` will sometimes fail due to reliance + // on registered fact + tokio::time::sleep(std::time::Duration::from_secs(2)).await; + trace!(target: LOG_TARGET, last_block, "Applying diffs."); let transaction_hash = dojo_os::starknet_apply_diffs( self.config.world_address,