diff --git a/crates/dojo/world/src/diff/manifest.rs b/crates/dojo/world/src/diff/manifest.rs index f4c7d03c6f..18f1039f46 100644 --- a/crates/dojo/world/src/diff/manifest.rs +++ b/crates/dojo/world/src/diff/manifest.rs @@ -33,6 +33,8 @@ pub struct WorldContract { pub seed: String, /// Name of the world. pub name: String, + /// Entrypoints of the world. + pub entrypoints: Vec, /// Abi of the world. pub abi: Vec, } @@ -53,6 +55,9 @@ pub struct DojoContract { pub init_calldata: Vec, /// Tag of the contract. pub tag: String, + /// Selector of the contract. + #[serde_as(as = "UfeHex")] + pub selector: Felt, /// Systems of the contract. pub systems: Vec, } @@ -68,6 +73,9 @@ pub struct DojoModel { pub class_hash: Felt, /// Tag of the model. pub tag: String, + /// Selector of the model. + #[serde_as(as = "UfeHex")] + pub selector: Felt, } #[serde_as] @@ -81,6 +89,9 @@ pub struct DojoEvent { pub class_hash: Felt, /// Tag of the event. pub tag: String, + /// Selector of the event. + #[serde_as(as = "UfeHex")] + pub selector: Felt, } /// Represents a model member. @@ -102,6 +113,7 @@ impl Manifest { address: diff.world_info.address, seed: diff.profile_config.world.seed.clone(), name: diff.profile_config.world.name.clone(), + entrypoints: diff.world_info.entrypoints.clone(), abi: diff.world_info.class.abi.clone(), }; @@ -147,6 +159,7 @@ fn resource_diff_to_dojo_contract(diff: &WorldDiff, resource: &ResourceDiff) -> init_calldata, tag, systems: l.systems.clone(), + selector: resource.dojo_selector(), }, ResourceDiff::Updated(ResourceLocal::Contract(l), ResourceRemote::Contract(r)) | ResourceDiff::Synced(ResourceLocal::Contract(l), ResourceRemote::Contract(r)) => { @@ -157,6 +170,7 @@ fn resource_diff_to_dojo_contract(diff: &WorldDiff, resource: &ResourceDiff) -> init_calldata, tag, systems: l.systems.clone(), + selector: resource.dojo_selector(), } } _ => unreachable!(), @@ -173,6 +187,7 @@ fn resource_diff_to_dojo_model(resource: &ResourceDiff) -> DojoModel { .collect(), class_hash: l.common.class_hash, tag: l.common.name.clone(), + selector: resource.dojo_selector(), }, ResourceDiff::Updated(ResourceLocal::Model(l), _) | ResourceDiff::Synced(ResourceLocal::Model(l), _) => DojoModel { @@ -183,6 +198,7 @@ fn resource_diff_to_dojo_model(resource: &ResourceDiff) -> DojoModel { .collect(), class_hash: l.common.class_hash, tag: l.common.name.clone(), + selector: resource.dojo_selector(), }, _ => unreachable!(), } @@ -198,6 +214,7 @@ fn resource_diff_to_dojo_event(resource: &ResourceDiff) -> DojoEvent { .collect(), class_hash: l.common.class_hash, tag: l.common.name.clone(), + selector: resource.dojo_selector(), }, ResourceDiff::Updated(ResourceLocal::Event(l), _) | ResourceDiff::Synced(ResourceLocal::Event(l), _) => DojoEvent { @@ -208,6 +225,7 @@ fn resource_diff_to_dojo_event(resource: &ResourceDiff) -> DojoEvent { .collect(), class_hash: l.common.class_hash, tag: l.common.name.clone(), + selector: resource.dojo_selector(), }, _ => unreachable!(), } diff --git a/crates/dojo/world/src/diff/mod.rs b/crates/dojo/world/src/diff/mod.rs index f9693e7669..8c00e03976 100644 --- a/crates/dojo/world/src/diff/mod.rs +++ b/crates/dojo/world/src/diff/mod.rs @@ -37,6 +37,8 @@ pub struct WorldStatusInfo { pub class: SierraClass, /// The status of the world. pub status: WorldStatus, + /// The entrypoints of the world. + pub entrypoints: Vec, } #[derive(Debug, PartialEq)] @@ -75,6 +77,7 @@ impl WorldDiff { casm_class_hash: local.casm_class_hash, class: local.class, status: WorldStatus::NotDeployed, + entrypoints: local.entrypoints, }, namespaces: vec![], resources: HashMap::new(), @@ -111,6 +114,7 @@ impl WorldDiff { class_hash: local.class_hash, casm_class_hash: local.casm_class_hash, class: local.class, + entrypoints: local.entrypoints, status, }, namespaces: vec![], diff --git a/crates/dojo/world/src/local/artifact_to_local.rs b/crates/dojo/world/src/local/artifact_to_local.rs index f67693d9d4..89e74ce513 100644 --- a/crates/dojo/world/src/local/artifact_to_local.rs +++ b/crates/dojo/world/src/local/artifact_to_local.rs @@ -7,7 +7,7 @@ use anyhow::Result; use cairo_lang_starknet_classes::casm_contract_class::CasmContractClass; use cairo_lang_starknet_classes::contract_class::ContractClass; use serde_json; -use starknet::core::types::contract::{AbiEntry, AbiImpl, SierraClass}; +use starknet::core::types::contract::{AbiEntry, AbiImpl, SierraClass, StateMutability}; use starknet::core::types::Felt; use tracing::trace; @@ -31,7 +31,7 @@ impl WorldLocal { let mut world_class = None; let mut world_class_hash = None; let mut world_casm_class_hash = None; - + let mut world_entrypoints = vec![]; for entry in fs::read_dir(dir)? { let entry = entry?; let path = entry.path(); @@ -57,11 +57,14 @@ impl WorldLocal { world_class = Some(sierra); world_class_hash = Some(class_hash); world_casm_class_hash = Some(casm_class_hash); + world_entrypoints = systems_from_abi(&abi); break; } ResourceType::Contract(name) => { let namespaces = profile_config.namespace.get_namespaces(&name); + let systems = systems_from_abi(&abi); + for ns in namespaces { trace!( name, @@ -77,7 +80,7 @@ impl WorldLocal { class_hash, casm_class_hash, }, - systems: vec![], + systems: systems.clone(), }); resources.push(resource); @@ -162,6 +165,7 @@ impl WorldLocal { casm_class_hash, resources: HashMap::new(), profile_config, + entrypoints: world_entrypoints, }, _ => { return Err(anyhow::anyhow!( @@ -227,6 +231,26 @@ fn name_from_impl(impl_name: &str) -> String { impl_name.split("__").collect::>()[0].to_string() } +fn systems_from_abi(abi: &[AbiEntry]) -> Vec { + fn extract_systems_from_abi_entry(entry: &AbiEntry) -> Vec { + match entry { + AbiEntry::Function(f) => { + if matches!(f.state_mutability, StateMutability::External) { + vec![f.name.clone()] + } else { + vec![] + } + } + AbiEntry::Interface(intf_entry) => { + intf_entry.items.iter().flat_map(extract_systems_from_abi_entry).collect() + } + _ => vec![], + } + } + + abi.iter().flat_map(extract_systems_from_abi_entry).collect() +} + #[cfg(test)] mod tests { use super::*; @@ -274,19 +298,56 @@ mod tests { ); } - #[ignore = "The simple example must be stabilized first (and built for this test to work)"] #[test] fn test_load_world_from_directory() { let namespace_config = NamespaceConfig::new("dojo"); let profile_config = ProfileConfig::new("test", "seed", namespace_config); - let world = WorldLocal::from_directory( - "/Users/glihm/cgg/dojo/examples/simple/target/dev", - profile_config, + let world = + WorldLocal::from_directory("../../../examples/simple/target/dev/", profile_config) + .unwrap(); + + assert!(world.class_hash != Felt::ZERO); + assert_eq!(world.resources.len(), 7); + assert_eq!( + world.entrypoints, + vec![ + "uuid", + "set_metadata", + "register_namespace", + "register_event", + "register_model", + "register_contract", + "init_contract", + "upgrade_event", + "upgrade_model", + "upgrade_contract", + "emit_event", + "emit_events", + "set_entity", + "set_entities", + "delete_entity", + "delete_entities", + "grant_owner", + "revoke_owner", + "grant_writer", + "revoke_writer", + "upgrade" + ] + ); + } + + #[test] + fn test_systems_from_abi() { + let abi = serde_json::from_reader::<_, SierraClass>( + std::fs::File::open( + "../../../examples/simple/target/dev/dojo_simple_c1.contract_class.json", + ) + .unwrap(), ) .unwrap(); - assert!(world.class_hash != Felt::ZERO); - assert_eq!(world.resources.len(), 3); + let systems = systems_from_abi(&abi.abi); + assert_eq!(systems, vec!["system_1", "system_2", "system_3", "system_4", "upgrade"]); } } diff --git a/crates/dojo/world/src/local/mod.rs b/crates/dojo/world/src/local/mod.rs index d24acb4a95..13e3934ab4 100644 --- a/crates/dojo/world/src/local/mod.rs +++ b/crates/dojo/world/src/local/mod.rs @@ -36,6 +36,9 @@ pub struct WorldLocal { pub resources: HashMap, /// The profile configuration of the local world. pub profile_config: ProfileConfig, + /// All the entrypoints that are exposed by the world + /// and can be targetted by a transaction. + pub entrypoints: Vec, } #[cfg(test)] @@ -64,6 +67,7 @@ impl Default for WorldLocal { casm_class_hash: Felt::ZERO, resources: HashMap::new(), profile_config: ProfileConfig::default(), + entrypoints: vec![], } } } diff --git a/examples/simple/manifest_dev.json b/examples/simple/manifest_dev.json index f202e7e3d0..7a06ef040f 100644 --- a/examples/simple/manifest_dev.json +++ b/examples/simple/manifest_dev.json @@ -1,9 +1,32 @@ { "world": { - "class_hash": "0x139239a99d627697b19b9856beaef7896fc75375caf3d750dd76982a7afeb78", - "address": "0x4bb1b5116e5ed181392417f0c18ade13246cb30447e4dba0f8421c80bb77e2e", + "class_hash": "0x2f92b70bd2b5a40ddef12c55257f245176870b25c7eb0bd7a60cf1f1f2fbf0e", + "address": "0x30e907536f553a4b90bbd008df0785061073e432f20779e0c3549923dd67576", "seed": "simple", "name": "simple", + "entrypoints": [ + "uuid", + "set_metadata", + "register_namespace", + "register_event", + "register_model", + "register_contract", + "init_contract", + "upgrade_event", + "upgrade_model", + "upgrade_contract", + "emit_event", + "emit_events", + "set_entity", + "set_entities", + "delete_entity", + "delete_entities", + "grant_owner", + "revoke_owner", + "grant_writer", + "revoke_writer", + "upgrade" + ], "abi": [ { "type": "impl", @@ -83,16 +106,12 @@ ] }, { - "type": "enum", - "name": "core::bool", - "variants": [ - { - "name": "False", - "type": "()" - }, + "type": "struct", + "name": "core::array::Span::>", + "members": [ { - "name": "True", - "type": "()" + "name": "snapshot", + "type": "@core::array::Array::>" } ] }, @@ -188,6 +207,30 @@ } ] }, + { + "type": "struct", + "name": "core::array::Span::", + "members": [ + { + "name": "snapshot", + "type": "@core::array::Array::" + } + ] + }, + { + "type": "enum", + "name": "core::bool", + "variants": [ + { + "name": "False", + "type": "()" + }, + { + "name": "True", + "type": "()" + } + ] + }, { "type": "interface", "name": "dojo::world::iworld::IWorld", @@ -398,10 +441,26 @@ { "name": "values", "type": "core::array::Span::" + } + ], + "outputs": [], + "state_mutability": "external" + }, + { + "type": "function", + "name": "emit_events", + "inputs": [ + { + "name": "event_selector", + "type": "core::felt252" }, { - "name": "historical", - "type": "core::bool" + "name": "keys", + "type": "core::array::Span::>" + }, + { + "name": "values", + "type": "core::array::Span::>" } ], "outputs": [], @@ -431,6 +490,30 @@ ], "state_mutability": "view" }, + { + "type": "function", + "name": "entities", + "inputs": [ + { + "name": "model_selector", + "type": "core::felt252" + }, + { + "name": "indexes", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::meta::layout::Layout" + } + ], + "outputs": [ + { + "type": "core::array::Span::>" + } + ], + "state_mutability": "view" + }, { "type": "function", "name": "set_entity", @@ -455,6 +538,30 @@ "outputs": [], "state_mutability": "external" }, + { + "type": "function", + "name": "set_entities", + "inputs": [ + { + "name": "model_selector", + "type": "core::felt252" + }, + { + "name": "indexes", + "type": "core::array::Span::" + }, + { + "name": "values", + "type": "core::array::Span::>" + }, + { + "name": "layout", + "type": "dojo::meta::layout::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "delete_entity", @@ -475,6 +582,26 @@ "outputs": [], "state_mutability": "external" }, + { + "type": "function", + "name": "delete_entities", + "inputs": [ + { + "name": "model_selector", + "type": "core::felt252" + }, + { + "name": "indexes", + "type": "core::array::Span::" + }, + { + "name": "layout", + "type": "dojo::meta::layout::Layout" + } + ], + "outputs": [], + "state_mutability": "external" + }, { "type": "function", "name": "is_owner", @@ -849,11 +976,6 @@ "type": "core::starknet::contract_address::ContractAddress", "kind": "key" }, - { - "name": "historical", - "type": "core::bool", - "kind": "key" - }, { "name": "keys", "type": "core::array::Span::", @@ -1121,14 +1243,24 @@ }, "contracts": [ { - "address": "0x16501c6eeae49a38af2a34e8c50a5ba6ac08c655e9c9b77b1306aad73aaca9d", - "class_hash": "0x13767b87a8459556babbcf8cbdf2800181b462ef47f6fdafc14fc14fc1dae57", + "address": "0xb03e5934197257ff6e03833bf34989930cd0fa49acd441995e5f40b08e96bc", + "class_hash": "0x758181d4a28c2a580c7ef9e963d4bcd5b0712320dc68a174c4f3ff4ad3eaae0", "abi": [ { "type": "impl", "name": "c1__ContractImpl", "interface_name": "dojo::contract::interface::IContract" }, + { + "type": "interface", + "name": "dojo::contract::interface::IContract", + "items": [] + }, + { + "type": "impl", + "name": "c1__DeployedContractImpl", + "interface_name": "dojo::meta::interface::IDeployedResource" + }, { "type": "struct", "name": "core::byte_array::ByteArray", @@ -1149,7 +1281,7 @@ }, { "type": "interface", - "name": "dojo::contract::interface::IContract", + "name": "dojo::meta::interface::IDeployedResource", "items": [ { "type": "function", @@ -1359,17 +1491,34 @@ "0xfffe" ], "tag": "ns-c1", - "systems": [] + "selector": "0x344f082f6bed98b4d02d4a9d4db43590c268f4c23bf0a31bfebafacd1806177", + "systems": [ + "system_1", + "system_2", + "system_3", + "system_4", + "upgrade" + ] }, { - "address": "0x707ff87e1260619aa7c41ebd7f12a32d8cc358565e539c9f7b85140af3ca285", - "class_hash": "0x1eef253239f61c49444c41990940fa8fee51b021d19e48c20d31f45bc465d46", + "address": "0x4664cdf8f8b36a99f441440a92252e40b4885a9973e0d0b38ca204ef2b3c4a1", + "class_hash": "0x2a400df88b0add6c980d281dc96354a5cfc2b886547e9ed621b097e21842ee6", "abi": [ { "type": "impl", "name": "c2__ContractImpl", "interface_name": "dojo::contract::interface::IContract" }, + { + "type": "interface", + "name": "dojo::contract::interface::IContract", + "items": [] + }, + { + "type": "impl", + "name": "c2__DeployedContractImpl", + "interface_name": "dojo::meta::interface::IDeployedResource" + }, { "type": "struct", "name": "core::byte_array::ByteArray", @@ -1390,7 +1539,7 @@ }, { "type": "interface", - "name": "dojo::contract::interface::IContract", + "name": "dojo::meta::interface::IDeployedResource", "items": [ { "type": "function", @@ -1522,17 +1671,30 @@ ], "init_calldata": [], "tag": "ns-c2", - "systems": [] + "selector": "0x7561c5d1d1d72352071ae8d14b5289444b3f2542b02daa2924c526fb0846e59", + "systems": [ + "upgrade" + ] }, { - "address": "0x41c67324187d806f29b4d02be6b358b9d0f68db4ae070d826d3a8149feba80f", - "class_hash": "0x4be29e651d49e58fba33f71ab6fe7fe101ee811842d07852b70d43a407fef2a", + "address": "0x151981aac48998f52e5d3189cf0fb0819ba642158425275a939d915e66bd2a3", + "class_hash": "0x7cc8d15e576873d544640f7fd124bd430bd19c0f31e203fb069b4fc2f5c0ab9", "abi": [ { "type": "impl", "name": "c3__ContractImpl", "interface_name": "dojo::contract::interface::IContract" }, + { + "type": "interface", + "name": "dojo::contract::interface::IContract", + "items": [] + }, + { + "type": "impl", + "name": "c3__DeployedContractImpl", + "interface_name": "dojo::meta::interface::IDeployedResource" + }, { "type": "struct", "name": "core::byte_array::ByteArray", @@ -1553,7 +1715,7 @@ }, { "type": "interface", - "name": "dojo::contract::interface::IContract", + "name": "dojo::meta::interface::IDeployedResource", "items": [ { "type": "function", @@ -1685,17 +1847,30 @@ ], "init_calldata": [], "tag": "ns-c3", - "systems": [] + "selector": "0x69bd1ce04aa3945bacae701a68e86c58b44d21c4debee8a65fa921b4a717c5f", + "systems": [ + "upgrade" + ] }, { - "address": "0x5d52f8c5bd309ba73977008086d7c7f9c0d2991d2e29e96f01f99bf2065f88e", - "class_hash": "0x13767b87a8459556babbcf8cbdf2800181b462ef47f6fdafc14fc14fc1dae57", + "address": "0x7b320d6a08aa96dd4bdcae3e031d6313e0628239c332e37584ed3ebaea133dd", + "class_hash": "0x758181d4a28c2a580c7ef9e963d4bcd5b0712320dc68a174c4f3ff4ad3eaae0", "abi": [ { "type": "impl", "name": "c1__ContractImpl", "interface_name": "dojo::contract::interface::IContract" }, + { + "type": "interface", + "name": "dojo::contract::interface::IContract", + "items": [] + }, + { + "type": "impl", + "name": "c1__DeployedContractImpl", + "interface_name": "dojo::meta::interface::IDeployedResource" + }, { "type": "struct", "name": "core::byte_array::ByteArray", @@ -1716,7 +1891,7 @@ }, { "type": "interface", - "name": "dojo::contract::interface::IContract", + "name": "dojo::meta::interface::IDeployedResource", "items": [ { "type": "function", @@ -1926,31 +2101,42 @@ "0xfffe" ], "tag": "ns2-c1", - "systems": [] + "selector": "0x11652d70e4b9b3ec4ddfe9277bbf7e44db1ce5d5d9ba5ab84b96de5db614d0", + "systems": [ + "system_1", + "system_2", + "system_3", + "system_4", + "upgrade" + ] } ], "models": [ { "members": [], - "class_hash": "0xb35ce9998d1524acfc8b0318aed7375b0d977b6362a2f7af23be2950aa96fd", - "tag": "M" + "class_hash": "0x506d770b7301fc791cf3a19705848647524a0e2595a4d38365df917b4d1d246", + "tag": "M", + "selector": "0x50aac05281bbfaa5393cacacc12e86f59ab7d5f3ee619427dd33a0756526f24" }, { "members": [], - "class_hash": "0xb35ce9998d1524acfc8b0318aed7375b0d977b6362a2f7af23be2950aa96fd", - "tag": "M" + "class_hash": "0x506d770b7301fc791cf3a19705848647524a0e2595a4d38365df917b4d1d246", + "tag": "M", + "selector": "0x3b26427a55dd1d51738b0e3e989fe6f25649e1311295f30f0a4fa2db439aa2c" } ], "events": [ { "members": [], - "class_hash": "0x65aa33d998d733abc890ee36503fe1df8e7c01f2cf1a92b147bd424a1af56d7", - "tag": "E" + "class_hash": "0x5c72f78327d896e16f3c9fe7ee5e136ad9fc4cda89fba1ce7e665877d477cd5", + "tag": "E", + "selector": "0x260e0511a6fa454a7d4ed8bea5fa52fc80fc588e33ba4cb58c65bbeeadf7565" }, { "members": [], - "class_hash": "0x58568a90180a44515609dbaf69bb0c1aa56f29e93688f4bfdab10268fe68ce1", - "tag": "EH" + "class_hash": "0x408fc887363634ee0d261cc26606574ce2bc433bedbcef4bb88f8fbc69a1e43", + "tag": "EH", + "selector": "0x4c6c7772b19b700cf97d078d02a419670d11d2b689a7a3647eac311b2817ced" } ] } \ No newline at end of file diff --git a/spawn-and-move-db.tar.gz b/spawn-and-move-db.tar.gz index 673110dfd4..00ba37748e 100644 Binary files a/spawn-and-move-db.tar.gz and b/spawn-and-move-db.tar.gz differ diff --git a/types-test-db.tar.gz b/types-test-db.tar.gz index 599996b2e8..bcf559c601 100644 Binary files a/types-test-db.tar.gz and b/types-test-db.tar.gz differ