diff --git a/Cargo.lock b/Cargo.lock index a8e2672a08..6be6e4c73a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2727,7 +2727,6 @@ dependencies = [ [[package]] name = "cairo-lang-macro" version = "0.1.0" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" dependencies = [ "cairo-lang-macro-attributes", "cairo-lang-macro-stable", @@ -3974,7 +3973,6 @@ dependencies = [ [[package]] name = "create-output-dir" version = "1.0.0" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" dependencies = [ "anyhow", "core-foundation 0.10.0", @@ -4631,43 +4629,6 @@ version = "1.0.0-rc.1" name = "dojo-examples-spawn-and-move" version = "1.0.0-rc.1" -[[package]] -name = "dojo-lang" -version = "1.0.0-rc.0" -source = "git+https://github.com/dojoengine/dojo?rev=479b698def87b004ecc074058182fac40d53d077#479b698def87b004ecc074058182fac40d53d077" -dependencies = [ - "anyhow", - "cairo-lang-compiler", - "cairo-lang-defs", - "cairo-lang-diagnostics", - "cairo-lang-filesystem", - "cairo-lang-plugins", - "cairo-lang-project", - "cairo-lang-semantic", - "cairo-lang-sierra-generator", - "cairo-lang-starknet", - "cairo-lang-starknet-classes", - "cairo-lang-syntax", - "cairo-lang-test-plugin", - "cairo-lang-utils", - "camino", - "convert_case 0.6.0", - "dojo-types 1.0.0-rc.0", - "indoc 1.0.9", - "itertools 0.12.1", - "regex", - "semver 1.0.23", - "serde", - "serde_json", - "serde_with 3.9.0", - "smol_str", - "starknet 0.12.0", - "tempfile", - "toml 0.8.19", - "tracing", - "url", -] - [[package]] name = "dojo-lang" version = "1.0.0-rc.1" @@ -4692,7 +4653,7 @@ dependencies = [ "cairo-lang-utils", "camino", "convert_case 0.6.0", - "dojo-types 1.0.0-rc.1", + "dojo-types", "indoc 1.0.9", "itertools 0.12.1", "once_cell", @@ -4717,7 +4678,7 @@ version = "1.0.0-rc.1" dependencies = [ "cairo-lang-language-server", "clap", - "dojo-lang 1.0.0-rc.1", + "dojo-lang", ] [[package]] @@ -4747,7 +4708,7 @@ dependencies = [ "assert_fs", "async-trait", "camino", - "dojo-lang 1.0.0-rc.1", + "dojo-lang", "dojo-world", "jsonrpsee 0.16.3", "katana-core", @@ -4764,27 +4725,6 @@ dependencies = [ "url", ] -[[package]] -name = "dojo-types" -version = "1.0.0-rc.0" -source = "git+https://github.com/dojoengine/dojo?rev=479b698def87b004ecc074058182fac40d53d077#479b698def87b004ecc074058182fac40d53d077" -dependencies = [ - "anyhow", - "cainome 0.4.6", - "crypto-bigint", - "hex", - "itertools 0.12.1", - "num-traits 0.2.19", - "regex", - "serde", - "serde_json", - "starknet 0.12.0", - "starknet-crypto 0.7.2", - "strum 0.25.0", - "strum_macros 0.25.3", - "thiserror", -] - [[package]] name = "dojo-types" version = "1.0.0-rc.1" @@ -4831,7 +4771,7 @@ dependencies = [ "async-trait", "cainome 0.4.6", "cairo-lang-starknet-classes", - "dojo-types 1.0.0-rc.1", + "dojo-types", "hex", "hex-literal", "ipfs-api-backend-hyper", @@ -7192,7 +7132,7 @@ dependencies = [ "iana-time-zone-haiku", "js-sys", "wasm-bindgen", - "windows-core 0.52.0", + "windows-core 0.51.1", ] [[package]] @@ -12355,8 +12295,7 @@ dependencies = [ [[package]] name = "scarb" -version = "2.8.4" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" +version = "2.8.2" dependencies = [ "anyhow", "async-trait", @@ -12386,7 +12325,7 @@ dependencies = [ "derive_builder", "dialoguer", "directories", - "dojo-lang 1.0.0-rc.0", + "dojo-lang", "dunce", "fs4", "fs_extra", @@ -12406,8 +12345,8 @@ dependencies = [ "redb", "reqwest 0.11.27", "scarb-build-metadata", - "scarb-metadata 1.12.0 (git+https://github.com/dojoengine/scarb?branch=dojo-284)", - "scarb-stable-hash 1.0.0 (git+https://github.com/dojoengine/scarb?branch=dojo-284)", + "scarb-metadata 1.12.0", + "scarb-stable-hash 1.0.0", "scarb-ui", "semver 1.0.23", "serde", @@ -12436,8 +12375,7 @@ dependencies = [ [[package]] name = "scarb-build-metadata" -version = "2.8.4" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" +version = "2.8.2" dependencies = [ "cargo_metadata", ] @@ -12445,10 +12383,9 @@ dependencies = [ [[package]] name = "scarb-metadata" version = "1.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "170ebce1774a85568646ba4096827f898306665187eebd9282fee313e316518d" dependencies = [ "camino", + "derive_builder", "semver 1.0.23", "serde", "serde_json", @@ -12458,10 +12395,10 @@ dependencies = [ [[package]] name = "scarb-metadata" version = "1.12.0" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "170ebce1774a85568646ba4096827f898306665187eebd9282fee313e316518d" dependencies = [ "camino", - "derive_builder", "semver 1.0.23", "serde", "serde_json", @@ -12471,8 +12408,6 @@ dependencies = [ [[package]] name = "scarb-stable-hash" version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1902536b23a05dd165d3992865870aaf1b0650317767cbf171ed2ca5903732a9" dependencies = [ "data-encoding", "xxhash-rust", @@ -12481,7 +12416,8 @@ dependencies = [ [[package]] name = "scarb-stable-hash" version = "1.0.0" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1902536b23a05dd165d3992865870aaf1b0650317767cbf171ed2ca5903732a9" dependencies = [ "data-encoding", "xxhash-rust", @@ -12490,14 +12426,13 @@ dependencies = [ [[package]] name = "scarb-ui" version = "0.1.5" -source = "git+https://github.com/dojoengine/scarb?branch=dojo-284#5ee01a699da7a973c38ba51eac1cb6065bb5006f" dependencies = [ "anyhow", "camino", "clap", "console", "indicatif", - "scarb-metadata 1.12.0 (git+https://github.com/dojoengine/scarb?branch=dojo-284)", + "scarb-metadata 1.12.0", "serde", "serde_json", "tracing-core", @@ -13244,9 +13179,9 @@ dependencies = [ "clap-verbosity-flag", "colored", "dojo-bindgen", - "dojo-lang 1.0.0-rc.1", + "dojo-lang", "dojo-test-utils", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "itertools 0.12.1", @@ -13287,7 +13222,7 @@ dependencies = [ "colored", "colored_json", "dojo-test-utils", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "futures", @@ -14873,7 +14808,7 @@ dependencies = [ "clap", "ctrlc", "dojo-metrics", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "either", @@ -14914,7 +14849,7 @@ dependencies = [ "async-trait", "camino", "crypto-bigint", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-world", "futures", "futures-util", @@ -14947,7 +14882,7 @@ dependencies = [ "chrono", "crypto-bigint", "dojo-test-utils", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "futures-channel", @@ -14986,7 +14921,7 @@ dependencies = [ "chrono", "convert_case 0.6.0", "dojo-test-utils", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "katana-runner", @@ -15021,7 +14956,7 @@ dependencies = [ "camino", "crypto-bigint", "dojo-test-utils", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-utils", "dojo-world", "futures", @@ -15068,7 +15003,7 @@ dependencies = [ "cainome 0.4.6", "chrono", "crypto-bigint", - "dojo-types 1.0.0-rc.1", + "dojo-types", "dojo-world", "futures", "indexmap 2.5.0", @@ -16408,15 +16343,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-core" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" -dependencies = [ - "windows-targets 0.52.6", -] - [[package]] name = "windows-core" version = "0.57.0" diff --git a/Cargo.toml b/Cargo.toml index d42daa8e17..702c871869 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -192,12 +192,10 @@ rpassword = "7.2.0" rstest = "0.18.2" rstest_reuse = "0.6.0" salsa = "0.16.1" -#scarb = { git = "https://github.com/software-mansion/scarb", tag = "v2.8.4" } -#scarb-ui = { git = "https://github.com/software-mansion/scarb", tag = "v2.8.4" } -scarb = { git = "https://github.com/dojoengine/scarb", branch = "dojo-284" } -scarb-ui = { git = "https://github.com/dojoengine/scarb", branch = "dojo-284" } -#scarb = { path = "/Users/glihm/swm/scarb/scarb" } -#scarb-ui = { path = "/Users/glihm/swm/scarb/utils/scarb-ui" } +#scarb = { git = "https://github.com/dojoengine/scarb", branch = "dojo-284" } +#scarb-ui = { git = "https://github.com/dojoengine/scarb", branch = "dojo-284" } +scarb = { path = "/Users/glihm/swm/scarb/scarb" } +scarb-ui = { path = "/Users/glihm/swm/scarb/utils/scarb-ui" } semver = "1.0.5" serde = { version = "1.0", features = [ "derive" ] } serde_json = { version = "1.0", features = [ "arbitrary_precision" ] } diff --git a/bin/sozo/src/commands/events.rs b/bin/sozo/src/commands/events.rs index 3a19ab6a7d..b7c59fc9c1 100644 --- a/bin/sozo/src/commands/events.rs +++ b/bin/sozo/src/commands/events.rs @@ -345,11 +345,9 @@ async fn match_event( ( format!("Event emitted ({})", tag), format!( - "Selector: {:#066x}\nContract: {}\nHistorical: {}\nKeys: {}\nValues: \ - {}\nData:\n{}", + "Selector: {:#066x}\nContract: {}\nKeys: {}\nValues: {}\nData:\n{}", e.selector, contract_tag, - e.historical, e.keys .iter() .map(|k| format!("{:#066x}", k)) diff --git a/bin/sozo/tests/test_data/policies.json b/bin/sozo/tests/test_data/policies.json index c48574cf3b..21a96941f6 100644 --- a/bin/sozo/tests/test_data/policies.json +++ b/bin/sozo/tests/test_data/policies.json @@ -1,118 +1,130 @@ [ { - "target": "0x197ece4113fa10c435129f63ffe00877c93446f36a8e3f803b846f76d496ed8", + "target": "0x7d7d295e7cab07d4a38f007b1c23717794352097c72cfb0885313fdff56eccb", "method": "upgrade" }, { - "target": "0x5e6ead52b5ea1146be22fdc3cffbc28d9eca3452f790f991a010ceeb12e339b", + "target": "0x2dfa01b63d923a818cd4b7fe40675638ca3df7e9abfd20cb7bc100dfef3a645", "method": "upgrade" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "spawn" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "move" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "set_player_config" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "reset_player_config" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "set_player_server_profile" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "set_models" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "enter_dungeon" }, { - "target": "0x48c075712ddb98febd836b09049e3d36c7b061fc7027ba5021f8cf00778b7bf", + "target": "0x77193b3008464a6db19a02e329d847a1f0e5041c7ca9d2abe145e95402879b7", "method": "upgrade" }, { - "target": "0x317a11a6cb0c66389ad53e1a9c282a64e8b94a7811b139da94138284ce019a4", + "target": "0x5a96bc248612b19a137e15597af8aaf0571f252cc0dd7916647f5d392904167", "method": "upgrade" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "uuid" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "set_metadata" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "register_namespace" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "register_event" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "register_model" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "register_contract" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "init_contract" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "upgrade_event" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "upgrade_model" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "upgrade_contract" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "emit_event" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", + "method": "emit_events" + }, + { + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "set_entity" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", + "method": "set_entities" + }, + { + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "delete_entity" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", + "method": "delete_entities" + }, + { + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "grant_owner" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "revoke_owner" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "grant_writer" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "revoke_writer" }, { - "target": "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115", + "target": "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc", "method": "upgrade" }, { diff --git a/crates/dojo/core-cairo-test/src/lib.cairo b/crates/dojo/core-cairo-test/src/lib.cairo index 3e9ca8017e..cc7bd30f21 100644 --- a/crates/dojo/core-cairo-test/src/lib.cairo +++ b/crates/dojo/core-cairo-test/src/lib.cairo @@ -47,6 +47,7 @@ mod tests { //mod entities; //mod resources; mod world; + mod storage; } mod utils { diff --git a/crates/dojo/core-cairo-test/src/tests/event/event.cairo b/crates/dojo/core-cairo-test/src/tests/event/event.cairo index 2c8e3e3bd0..2753abdcc8 100644 --- a/crates/dojo/core-cairo-test/src/tests/event/event.cairo +++ b/crates/dojo/core-cairo-test/src/tests/event/event.cairo @@ -1,3 +1,4 @@ +#[derive(Drop, Serde)] #[dojo::event] struct FooEvent { #[key] @@ -13,7 +14,6 @@ fn test_event_definition() { let definition = dojo::event::Event::::definition(); assert_eq!(definition.name, dojo::event::Event::::name()); - assert_eq!(definition.version, dojo::event::Event::::version()); assert_eq!(definition.layout, dojo::event::Event::::layout()); assert_eq!(definition.schema, dojo::event::Event::::schema()); } diff --git a/crates/dojo/core-cairo-test/src/tests/helpers.cairo b/crates/dojo/core-cairo-test/src/tests/helpers.cairo index ca53dda73f..083703213c 100644 --- a/crates/dojo/core-cairo-test/src/tests/helpers.cairo +++ b/crates/dojo/core-cairo-test/src/tests/helpers.cairo @@ -26,6 +26,15 @@ pub struct Foo { pub b: u128, } +#[derive(Drop, Serde, Debug)] +#[dojo::model] +pub struct NotCopiable { + #[key] + pub caller: ContractAddress, + pub a: Array, + pub b: ByteArray, +} + #[starknet::contract] pub mod foo_invalid_name { use dojo::model::IModel; @@ -208,7 +217,10 @@ pub fn deploy_world() -> WorldStorage { /// No permissions are granted. pub fn deploy_world_and_foo() -> (WorldStorage, felt252) { let namespace_def = NamespaceDef { - namespace: "dojo", resources: [TestResource::Model(m_Foo::TEST_CLASS_HASH)].span(), + namespace: "dojo", resources: [ + TestResource::Model(m_Foo::TEST_CLASS_HASH), + TestResource::Model(m_NotCopiable::TEST_CLASS_HASH), + ].span(), }; (spawn_test_world([namespace_def].span()), Model::::selector(DOJO_NSH)) diff --git a/crates/dojo/core-cairo-test/src/tests/world/storage.cairo b/crates/dojo/core-cairo-test/src/tests/world/storage.cairo new file mode 100644 index 0000000000..d8f902ecc0 --- /dev/null +++ b/crates/dojo/core-cairo-test/src/tests/world/storage.cairo @@ -0,0 +1,128 @@ +use dojo::model::ModelStorage; + +use crate::tests::helpers::{deploy_world_and_foo, Foo, NotCopiable}; + +#[test] +fn write_simple() { + let (mut world, _) = deploy_world_and_foo(); + + let bob = 0xb0b.try_into().unwrap(); + + let foo: Foo = world.read_model(bob); + assert_eq!(foo.caller, bob); + assert_eq!(foo.a, 0); + assert_eq!(foo.b, 0); + + let foo = Foo { caller: bob, a: 1, b: 2 }; + world.write_model(@foo); + + let foo: Foo = world.read_model(bob); + assert_eq!(foo.caller, bob); + assert_eq!(foo.a, 1); + assert_eq!(foo.b, 2); + + world.erase_model(@foo); + + let foo: Foo = world.read_model(bob); + assert_eq!(foo.caller, bob); + assert_eq!(foo.a, 0); + assert_eq!(foo.b, 0); +} + +#[test] +fn write_multiple_copiable() { + let (mut world, _) = deploy_world_and_foo(); + + let mut models_snaps: Array<@Foo> = array![]; + let mut keys: Array = array![]; + + for i in 0_u128 + ..10_u128 { + let felt: felt252 = i.into(); + let caller: starknet::ContractAddress = felt.try_into().unwrap(); + keys.append(caller); + + if i % 2 == 0 { + let foo = Foo { caller, a: felt, b: i }; + models_snaps.append(@foo); + } else { + let foo = Foo { caller, a: felt, b: i }; + models_snaps.append(@foo); + } + }; + + world.write_models(models_snaps.span()); + + let mut models: Array = world.read_models(keys.span()); + + assert_eq!(models.len(), 10); + + for i in 0_u128 + ..10_u128 { + let felt: felt252 = i.into(); + let caller: starknet::ContractAddress = felt.try_into().unwrap(); + // Can desnap as copiable. + let model: Foo = *models[i.try_into().unwrap()]; + assert_eq!(model.caller, caller); + assert_eq!(model.a, felt); + assert_eq!(model.b, i); + }; + + world.erase_models(models_snaps.span()); + + let mut models: Array = world.read_models(keys.span()); + + while let Option::Some(m) = models.pop_front() { + assert_eq!(m.a, 0); + assert_eq!(m.b, 0); + }; +} + +#[test] +fn write_multiple_not_copiable() { + let (mut world, _) = deploy_world_and_foo(); + + let mut models_snaps: Array<@NotCopiable> = array![]; + let mut keys: Array = array![]; + + for i in 0_u128 + ..10_u128 { + let felt: felt252 = i.into(); + let caller: starknet::ContractAddress = felt.try_into().unwrap(); + keys.append(caller); + + if i % 2 == 0 { + let foo = NotCopiable { caller, a: array![felt], b: "ab" }; + models_snaps.append(@foo); + } else { + let foo = NotCopiable { caller, a: array![felt], b: "ab" }; + models_snaps.append(@foo); + } + }; + + world.write_models(models_snaps.span()); + + let mut models: Array = world.read_models(keys.span()); + + assert_eq!(models.len(), 10); + + for i in 0_u128 + ..10_u128 { + let felt: felt252 = i.into(); + let caller: starknet::ContractAddress = felt.try_into().unwrap(); + // Can desnap as copiable. + let model: NotCopiable = *models[i.try_into().unwrap()]; + assert_eq!(model.caller, caller); + assert_eq!(model.a, array![felt]); + assert_eq!(model.b, "ab"); + }; + + world.erase_models(models_snaps.span()); + + let mut models: Array = world.read_models(keys.span()); + + while let Option::Some(m) = models.pop_front() { + assert_eq!(m.a, array![]); + assert_eq!(m.b, ""); + }; +} diff --git a/crates/dojo/core-cairo-test/src/tests/world/world.cairo b/crates/dojo/core-cairo-test/src/tests/world/world.cairo index e394feb314..47b6818a50 100644 --- a/crates/dojo/core-cairo-test/src/tests/world/world.cairo +++ b/crates/dojo/core-cairo-test/src/tests/world/world.cairo @@ -99,7 +99,6 @@ fn test_emit() { 'bad event selector' ); assert(event.system_address == bob, 'bad system address'); - assert(!event.historical, 'bad historical value'); assert(event.keys == [2].span(), 'bad keys'); assert(event.values == [3, 4].span(), 'bad values'); } else { diff --git a/crates/dojo/core/src/event/event.cairo b/crates/dojo/core/src/event/event.cairo index 16b08256dc..0a5cf996b8 100644 --- a/crates/dojo/core/src/event/event.cairo +++ b/crates/dojo/core/src/event/event.cairo @@ -4,18 +4,15 @@ use dojo::meta::introspect::Ty; #[derive(Drop, Serde, Debug, PartialEq)] pub struct EventDefinition { pub name: ByteArray, - pub version: u8, pub layout: Layout, pub schema: Ty } pub trait Event { fn name() -> ByteArray; - fn version() -> u8; fn definition() -> EventDefinition; fn layout() -> Layout; fn schema() -> Ty; - fn historical() -> bool; fn keys(self: @T) -> Span; fn values(self: @T) -> Span; /// Returns the selector of the model computed for the given namespace hash. diff --git a/crates/dojo/core/src/event/interface.cairo b/crates/dojo/core/src/event/interface.cairo index 0003657113..4bc5b4f3d1 100644 --- a/crates/dojo/core/src/event/interface.cairo +++ b/crates/dojo/core/src/event/interface.cairo @@ -6,7 +6,6 @@ use super::EventDefinition; #[starknet::interface] pub trait IEvent { fn dojo_name(self: @T) -> ByteArray; - fn version(self: @T) -> u8; fn definition(self: @T) -> EventDefinition; fn layout(self: @T) -> Layout; fn schema(self: @T) -> Ty; diff --git a/crates/dojo/core/src/lib.cairo b/crates/dojo/core/src/lib.cairo index 37a82eca06..e08ce065d6 100644 --- a/crates/dojo/core/src/lib.cairo +++ b/crates/dojo/core/src/lib.cairo @@ -49,12 +49,6 @@ pub mod model { pub use storage::{ ModelStorage, ModelStorageTest, ModelValueStorage, ModelValueStorageTest, ModelPtr, }; - - #[cfg(target: "test")] - pub use model::{ModelTest}; - - #[cfg(target: "test")] - pub use model_value::{ModelValueTest}; } pub mod storage { diff --git a/crates/dojo/core/src/model/model.cairo b/crates/dojo/core/src/model/model.cairo index 9a6d941ea9..7a3bcd91b5 100644 --- a/crates/dojo/core/src/model/model.cairo +++ b/crates/dojo/core/src/model/model.cairo @@ -119,25 +119,3 @@ pub impl ModelImpl, +ModelDefinition, +Serde> of Model< } } } - -/// The `ModelTest` trait. -/// -/// It provides a standardized way to interact with models for testing purposes, -/// bypassing the permission checks. -#[cfg(target: "test")] -pub trait ModelTest { - fn set_model_test(ref self: S, model: @M); - fn delete_model_test(ref self: S, model: @M); -} - -/// The `ModelTestImpl` implementation for testing purposes. -#[cfg(target: "test")] -pub impl ModelTestImpl, +Model> of ModelTest { - fn set_model_test(ref self: S, model: @M) { - dojo::model::ModelStorageTest::::write_model_test(ref self, model); - } - - fn delete_model_test(ref self: S, model: @M) { - dojo::model::ModelStorageTest::::erase_model_test(ref self, model); - } -} diff --git a/crates/dojo/core/src/model/model_value.cairo b/crates/dojo/core/src/model/model_value.cairo index ccb02d06e8..eb0468bf4d 100644 --- a/crates/dojo/core/src/model/model_value.cairo +++ b/crates/dojo/core/src/model/model_value.cairo @@ -60,27 +60,3 @@ pub impl ModelValueImpl, +ModelDefinition, +ModelValueParser> dojo::utils::selector_from_namespace_and_name(namespace_hash, @Self::name()) } } - - -/// Test implementation of the `ModelValueTest` trait to bypass permission checks. -#[cfg(target: "test")] -pub trait ModelValueTest { - fn update_test(ref self: S, entity_id: felt252, value: @V); - fn delete_test(ref self: S, entity_id: felt252); -} - -/// Implementation of the `ModelValueTest` trait for testing purposes, bypassing permission checks. -#[cfg(target: "test")] -pub impl ModelValueTestImpl< - S, V, +super::storage::ModelValueStorageTest, +ModelValue -> of ModelValueTest { - fn update_test(ref self: S, entity_id: felt252, value: @V) { - super::storage::ModelValueStorageTest::< - S, V - >::write_value_from_id_test(ref self, entity_id, value) - } - - fn delete_test(ref self: S, entity_id: felt252) { - super::storage::ModelValueStorageTest::::erase_value_from_id_test(ref self, entity_id) - } -} diff --git a/crates/dojo/core/src/model/storage.cairo b/crates/dojo/core/src/model/storage.cairo index 1cf86528e0..ca9336bbd4 100644 --- a/crates/dojo/core/src/model/storage.cairo +++ b/crates/dojo/core/src/model/storage.cairo @@ -20,16 +20,30 @@ pub trait ModelStorage { /// Sets a model of type `M`. fn write_model(ref self: S, model: @M); + /// Sets multiple models of type `M`. + fn write_models(ref self: S, models: Span<@M>); + /// Retrieves a model of type `M` using the provided key of type `K`. fn read_model, +Serde>(self: @S, key: K) -> M; + /// Retrieves multiple models of type `M` using the provided keys of type `K`. + /// Returnes an array to ensure the user can consume the models, even if the type is not + /// copiable. + fn read_models, +Serde>(self: @S, keys: Span) -> Array; + /// Deletes a model of type `M`. fn erase_model(ref self: S, model: @M); + /// Deletes multiple models of type `M`. + fn erase_models(ref self: S, models: Span<@M>); + /// Deletes a model of type `M` using the provided entity id. /// The ptr is mostly used for type inferrence. fn erase_model_ptr(ref self: S, ptr: ModelPtr); + /// Deletes multiple models of type `M` using the provided entity ids. + fn erase_models_ptrs(ref self: S, ptrs: Span>); + /// Returns the current namespace hash. fn namespace_hash(self: @S) -> felt252; } @@ -39,14 +53,30 @@ pub trait ModelValueStorage { /// Retrieves a model value of type `V` using the provided key of type `K`. fn read_value, +Serde, +ModelValueKey>(self: @S, key: K) -> V; + /// Retrieves multiple model values of type `V` using the provided keys of type `K`. + fn read_values, +Serde, +ModelValueKey>( + self: @S, keys: Span + ) -> Array; + /// Retrieves a model value of type `V` using the provided entity id. fn read_value_from_id(self: @S, entity_id: felt252) -> V; + /// Retrieves multiple model values of type `V` using the provided entity ids. + fn read_values_from_ids(self: @S, entity_ids: Span) -> Array; + /// Updates a model value of type `V`. fn write_value, +Serde, +ModelValueKey>(ref self: S, key: K, value: @V); + /// Updates multiple model values of type `V`. + fn write_values, +Serde, +ModelValueKey>( + ref self: S, keys: Span, values: Span<@V> + ); + /// Updates a model value of type `V`. fn write_value_from_id(ref self: S, entity_id: felt252, value: @V); + + /// Updates multiple model values of type `V`. + fn write_values_from_ids(ref self: S, entity_ids: Span, values: Span<@V>); } /// A `ModelStorage` trait that abstracts where the storage is. @@ -56,10 +86,16 @@ pub trait ModelValueStorage { pub trait ModelStorageTest { /// Sets a model of type `M`. fn write_model_test(ref self: S, model: @M); + /// Sets multiple models of type `M`. + fn write_models_test(ref self: S, models: Span<@M>); /// Deletes a model of type `M`. fn erase_model_test(ref self: S, model: @M); + /// Deletes multiple models of type `M`. + fn erase_models_test(ref self: S, models: Span<@M>); /// Deletes a model of type `M` using the provided entity id. fn erase_model_ptr_test(ref self: S, ptr: ModelPtr); + /// Deletes multiple models of type `M` using the provided entity ids. + fn erase_models_ptrs_test(ref self: S, ptrs: Span>); } /// A `ModelValueStorageTest` trait that abstracts where the storage is and bypass the permission @@ -69,8 +105,12 @@ pub trait ModelValueStorageTest { fn write_value_test, +Serde, +ModelValueKey>( ref self: S, key: K, value: @V ); + /// Updates multiple model values of type `V`. + fn write_values_test, +Serde, +ModelValueKey>( + ref self: S, keys: Span, values: Span<@V> + ); /// Updates a model value of type `V`. fn write_value_from_id_test(ref self: S, entity_id: felt252, value: @V); - /// Deletes a model value of type `V`. - fn erase_value_from_id_test(ref self: S, entity_id: felt252); + /// Updates multiple model values of type `V`. + fn write_values_from_ids_test(ref self: S, entity_ids: Span, values: Span<@V>); } diff --git a/crates/dojo/core/src/world/errors.cairo b/crates/dojo/core/src/world/errors.cairo index 9f71452d92..b96823bcab 100644 --- a/crates/dojo/core/src/world/errors.cairo +++ b/crates/dojo/core/src/world/errors.cairo @@ -2,6 +2,10 @@ use starknet::ContractAddress; pub const DELETE_ENTITY_MEMBER: felt252 = 'Cannot delete entity member'; +pub fn lengths_mismatch(a: @ByteArray, b: @ByteArray, context: @ByteArray) -> ByteArray { + format!("Length mismatch: `{a}` and `{b}` in `{context}`") +} + pub fn not_writer(contract_tag: @ByteArray, on_type: @ByteArray, on_tag: @ByteArray) -> ByteArray { format!("Caller `{}` has no write access on {} `{}`", contract_tag, on_type, on_tag) } diff --git a/crates/dojo/core/src/world/iworld.cairo b/crates/dojo/core/src/world/iworld.cairo index 7cdf54af0d..b11dfb67ec 100644 --- a/crates/dojo/core/src/world/iworld.cairo +++ b/crates/dojo/core/src/world/iworld.cairo @@ -126,13 +126,23 @@ pub trait IWorld { /// * `event_selector` - The selector of the event. /// * `keys` - The keys of the event. /// * `values` - The data to be logged by the event. - /// * `historical` - Whether the event should be logged in historical mode. fn emit_event( + ref self: T, event_selector: felt252, keys: Span, values: Span, + ); + + /// Emits multiple events. + /// Permissions are only checked once, then the events are batched. + /// + /// # Arguments + /// + /// * `event_selector` - The selector of the event. + /// * `keys` - The keys of the event. + /// * `values` - The data to be logged by the event. + fn emit_events( ref self: T, event_selector: felt252, - keys: Span, - values: Span, - historical: bool + keys: Span>, + values: Span>, ); /// Gets the values of a model entity/member. @@ -151,6 +161,17 @@ pub trait IWorld { self: @T, model_selector: felt252, index: ModelIndex, layout: Layout ) -> Span; + /// Gets the model values for the given entities. + /// + /// # Arguments + /// + /// * `model_selector` - The selector of the model to be retrieved. + /// * `indices` - The indexes of the entities/members to read. + /// * `layout` - The memory layout of the model. + fn entities( + self: @T, model_selector: felt252, indexes: Span, layout: Layout + ) -> Span>; + /// Sets the model value for the given entity/member. /// /// # Arguments @@ -167,6 +188,23 @@ pub trait IWorld { layout: Layout ); + /// Sets the model values for the given entities. + /// The permissions are only checked once, then the writes are batched. + /// + /// # Arguments + /// + /// * `model_selector` - The selector of the model to be set. + /// * `indexes` - The indexes of the entities/members to write. + /// * `values` - The values to be set, serialized using the model layout format. + /// * `layout` - The memory layout of the model. + fn set_entities( + ref self: T, + model_selector: felt252, + indexes: Span, + values: Span>, + layout: Layout + ); + /// Deletes a model value for the given entity/member. /// Deleting is setting all the values to 0 in the given layout. /// @@ -177,6 +215,18 @@ pub trait IWorld { /// * `layout` - The memory layout of the model. fn delete_entity(ref self: T, model_selector: felt252, index: ModelIndex, layout: Layout); + /// Deletes the model values for the given entities. + /// The permissions are only checked once, then the deletes are batched. + /// + /// # Arguments + /// + /// * `model_selector` - The selector of the model to be deleted. + /// * `indexes` - The indexes of the entities/members to delete. + /// * `layout` - The memory layout of the model. + fn delete_entities( + ref self: T, model_selector: felt252, indexes: Span, layout: Layout + ); + /// Returns true if the provided account has owner permission for the resource, false otherwise. /// /// # Arguments @@ -258,11 +308,7 @@ pub trait IWorldTest { /// Emits a custom event that was previously registered in the world without checking for /// resource permissions. fn emit_event_test( - ref self: T, - event_selector: felt252, - keys: Span, - values: Span, - historical: bool + ref self: T, event_selector: felt252, keys: Span, values: Span, ); /// Returns the address of a registered contract, panics otherwise. diff --git a/crates/dojo/core/src/world/storage.cairo b/crates/dojo/core/src/world/storage.cairo index e922d882e5..1ea1c0719b 100644 --- a/crates/dojo/core/src/world/storage.cairo +++ b/crates/dojo/core/src/world/storage.cairo @@ -52,7 +52,6 @@ pub impl EventStorageWorldStorageImpl> of EventStorage::selector(self.namespace_hash), Event::::keys(event), Event::::values(event), - Event::::historical() ); } } @@ -76,6 +75,46 @@ pub impl ModelStorageWorldStorageImpl, +Drop> of ModelStorage, +Serde>(self: @WorldStorage, keys: Span) -> Array { + let mut indexes: Array = array![]; + + for k in keys { + indexes.append(ModelIndex::Keys(serialize_inline::(k))); + }; + + let all_values = IWorldDispatcherTrait::entities( + *self.dispatcher, + Model::::selector(*self.namespace_hash), + indexes.span(), + Model::::layout() + ); + + let mut models: Array = array![]; + + let mut i = 0; + loop { + if i >= indexes.len() { + break; + } + + let mut mk = serialize_inline::(keys[i]); + let mut mv = *all_values[i]; + + match Model::::from_values(ref mk, ref mv) { + Option::Some(model) => models.append(model), + Option::None => { + panic!( + "Model: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + ) + } + }; + + i += 1; + }; + + models + } + fn write_model(ref self: WorldStorage, model: @M) { IWorldDispatcherTrait::set_entity( self.dispatcher, @@ -86,6 +125,23 @@ pub impl ModelStorageWorldStorageImpl, +Drop> of ModelStorage) { + let mut keys: Array = array![]; + let mut values: Array> = array![]; + for m in models { + keys.append(ModelIndex::Keys(Model::::keys(*m))); + values.append(Model::::values(*m)); + }; + + IWorldDispatcherTrait::set_entities( + self.dispatcher, + Model::::selector(self.namespace_hash), + keys.span(), + values.span(), + Model::::layout() + ); + } + fn erase_model(ref self: WorldStorage, model: @M) { IWorldDispatcherTrait::delete_entity( self.dispatcher, @@ -95,6 +151,20 @@ pub impl ModelStorageWorldStorageImpl, +Drop> of ModelStorage) { + let mut keys: Array = array![]; + for m in models { + keys.append(ModelIndex::Keys(Model::::keys(*m))); + }; + + IWorldDispatcherTrait::delete_entities( + self.dispatcher, + Model::::selector(self.namespace_hash), + keys.span(), + Model::::layout() + ); + } + fn erase_model_ptr(ref self: WorldStorage, ptr: ModelPtr) { let entity_id = match ptr { ModelPtr::Id(id) => id, @@ -109,13 +179,33 @@ pub impl ModelStorageWorldStorageImpl, +Drop> of ModelStorage>) { + let mut indexes: Array = array![]; + for p in ptrs { + indexes + .append( + match p { + ModelPtr::Id(id) => ModelIndex::Id(*id), + ModelPtr::Keys(keys) => ModelIndex::Id(entity_id_from_keys(*keys)), + } + ); + }; + + IWorldDispatcherTrait::delete_entities( + self.dispatcher, + Model::::selector(self.namespace_hash), + indexes.span(), + Model::::layout() + ); + } + fn namespace_hash(self: @WorldStorage) -> felt252 { *self.namespace_hash } } impl ModelValueStorageWorldStorageImpl< - V, +ModelValue + V, +ModelValue, +Drop > of dojo::model::ModelValueStorage { fn read_value, +Serde, +ModelValueKey>(self: @WorldStorage, key: K) -> V { Self::read_value_from_id(self, entity_id_from_key(@key)) @@ -138,6 +228,55 @@ impl ModelValueStorageWorldStorageImpl< } } + fn read_values, +Serde, +ModelValueKey>( + self: @WorldStorage, keys: Span + ) -> Array { + let mut entity_ids: Array = array![]; + for k in keys { + entity_ids.append(entity_id_from_key(k)); + }; + + Self::read_values_from_ids(self, entity_ids.span()) + } + + fn read_values_from_ids(self: @WorldStorage, entity_ids: Span) -> Array { + let mut indexes: Array = array![]; + for id in entity_ids { + indexes.append(ModelIndex::Id(*id)); + }; + + let mut all_values = IWorldDispatcherTrait::entities( + *self.dispatcher, + ModelValue::::selector(*self.namespace_hash), + indexes.span(), + ModelValue::::layout() + ); + + let mut values: Array = array![]; + let mut i = 0; + loop { + if i >= indexes.len() { + break; + } + + let entity_id = *entity_ids[i]; + let mut v = *all_values[i]; + + match ModelValue::::from_values(entity_id, ref v) { + Option::Some(value) => values.append(value), + Option::None => { + panic!( + "Value: deserialization failed. Ensure the length of the keys tuple is matching the number of #[key] fields in the model struct." + ) + } + } + + i += 1; + }; + + values + } + fn write_value, +Serde, +ModelValueKey>( ref self: WorldStorage, key: K, value: @V ) { @@ -151,6 +290,17 @@ impl ModelValueStorageWorldStorageImpl< ); } + fn write_values, +Serde, +ModelValueKey>( + ref self: WorldStorage, keys: Span, values: Span<@V> + ) { + let mut ids: Array = array![]; + for k in keys { + ids.append(entity_id_from_key(k)); + }; + + Self::write_values_from_ids(ref self, ids.span(), values); + } + fn write_value_from_id(ref self: WorldStorage, entity_id: felt252, value: @V) { IWorldDispatcherTrait::set_entity( self.dispatcher, @@ -160,6 +310,31 @@ impl ModelValueStorageWorldStorageImpl< ModelValue::::layout() ); } + + fn write_values_from_ids(ref self: WorldStorage, entity_ids: Span, values: Span<@V>) { + let mut indexes: Array = array![]; + let mut all_values: Array> = array![]; + let mut i = 0; + + loop { + if i >= entity_ids.len() { + break; + } + + indexes.append(ModelIndex::Id(*entity_ids[i])); + all_values.append(ModelValue::::values(*values[i])); + + i += 1; + }; + + IWorldDispatcherTrait::set_entities( + self.dispatcher, + ModelValue::::selector(self.namespace_hash), + indexes.span(), + all_values.span(), + ModelValue::::layout() + ); + } } #[cfg(target: "test")] @@ -175,7 +350,6 @@ pub impl EventStorageTestWorldStorageImpl< Event::::selector(self.namespace_hash), Event::::keys(event), Event::::values(event), - Event::::historical() ); } } @@ -199,6 +373,12 @@ pub impl ModelStorageTestWorldStorageImpl< ); } + fn write_models_test(ref self: WorldStorage, models: Span<@M>) { + for m in models { + Self::write_model_test(ref self, *m); + } + } + fn erase_model_test(ref self: WorldStorage, model: @M) { let world_test = dojo::world::IWorldTestDispatcher { contract_address: self.dispatcher.contract_address @@ -212,6 +392,12 @@ pub impl ModelStorageTestWorldStorageImpl< ); } + fn erase_models_test(ref self: WorldStorage, models: Span<@M>) { + for m in models { + Self::erase_model_test(ref self, *m); + } + } + fn erase_model_ptr_test(ref self: WorldStorage, ptr: ModelPtr) { let entity_id = match ptr { ModelPtr::Id(id) => id, @@ -229,6 +415,32 @@ pub impl ModelStorageTestWorldStorageImpl< Model::::layout() ); } + + fn erase_models_ptrs_test(ref self: WorldStorage, ptrs: Span>) { + let mut ids: Array = array![]; + for p in ptrs { + ids + .append( + match p { + ModelPtr::Id(id) => *id, + ModelPtr::Keys(keys) => entity_id_from_keys(*keys), + } + ); + }; + + let world_test = dojo::world::IWorldTestDispatcher { + contract_address: self.dispatcher.contract_address + }; + + for i in ids { + dojo::world::IWorldTestDispatcherTrait::delete_entity_test( + world_test, + Model::::selector(self.namespace_hash), + ModelIndex::Id(i), + Model::::layout() + ); + } + } } /// Implementation of the `ModelValueStorageTest` trait for testing purposes, bypassing permission @@ -244,6 +456,17 @@ pub impl ModelValueStorageTestWorldStorageImpl< Self::write_value_from_id_test(ref self, dojo::utils::entity_id_from_keys(keys), value); } + fn write_values_test, +Serde, +ModelValueKey>( + ref self: WorldStorage, keys: Span, values: Span<@V> + ) { + let mut ids: Array = array![]; + for k in keys { + ids.append(entity_id_from_key(k)); + }; + + Self::write_values_from_ids_test(ref self, ids.span(), values); + } + fn write_value_from_id_test(ref self: WorldStorage, entity_id: felt252, value: @V) { let world_test = dojo::world::IWorldTestDispatcher { contract_address: self.dispatcher.contract_address @@ -258,17 +481,19 @@ pub impl ModelValueStorageTestWorldStorageImpl< ); } - fn erase_value_from_id_test(ref self: WorldStorage, entity_id: felt252) { - let world_test = dojo::world::IWorldTestDispatcher { - contract_address: self.dispatcher.contract_address - }; + fn write_values_from_ids_test( + ref self: WorldStorage, entity_ids: Span, values: Span<@V> + ) { + let mut i = 0; + loop { + if i >= entity_ids.len() { + break; + } - dojo::world::IWorldTestDispatcherTrait::delete_entity_test( - world_test, - ModelValue::::selector(self.namespace_hash), - ModelIndex::Id(entity_id), - ModelValue::::layout() - ); + Self::write_value_from_id_test(ref self, *entity_ids[i], *values[i]); + + i += 1; + } } } diff --git a/crates/dojo/core/src/world/world_contract.cairo b/crates/dojo/core/src/world/world_contract.cairo index c37fd2967f..321d542b6f 100644 --- a/crates/dojo/core/src/world/world_contract.cairo +++ b/crates/dojo/core/src/world/world_contract.cairo @@ -226,8 +226,6 @@ pub mod world { pub selector: felt252, #[key] pub system_address: ContractAddress, - #[key] - pub historical: bool, pub keys: Span, pub values: Span, } @@ -302,16 +300,11 @@ pub mod world { event_selector: felt252, keys: Span, values: Span, - historical: bool ) { self .emit( EventEmitted { - selector: event_selector, - system_address: get_caller_address(), - historical, - keys, - values + selector: event_selector, system_address: get_caller_address(), keys, values } ); } @@ -784,7 +777,6 @@ pub mod world { event_selector: felt252, keys: Span, values: Span, - historical: bool ) { if let Resource::Event((_, _)) = self.resources.read(event_selector) { self.assert_caller_permissions(event_selector, Permission::Writer); @@ -794,7 +786,6 @@ pub mod world { EventEmitted { selector: event_selector, system_address: get_caller_address(), - historical, keys, values, } @@ -806,28 +797,63 @@ pub mod world { } } + fn emit_events( + ref self: ContractState, + event_selector: felt252, + keys: Span>, + values: Span>, + ) { + if let Resource::Event((_, _)) = self.resources.read(event_selector) { + self.assert_caller_permissions(event_selector, Permission::Writer); + + if keys.len() != values.len() { + panic_with_byte_array( + @errors::lengths_mismatch(@"keys", @"values", @"emit_events") + ); + } + + let mut i = 0; + loop { + if i >= keys.len() { + break; + } + + self + .emit( + EventEmitted { + selector: event_selector, + system_address: get_caller_address(), + keys: *keys[i], + values: *values[i], + } + ); + + i += 1; + } + } else { + panic_with_byte_array( + @errors::resource_conflict(@format!("{event_selector}"), @"event") + ); + } + } + fn entity( self: @ContractState, model_selector: felt252, index: ModelIndex, layout: Layout ) -> Span { - match index { - ModelIndex::Keys(keys) => { - let entity_id = entity_id_from_keys(keys); - storage::entity_model::read_model_entity(model_selector, entity_id, layout) - }, - ModelIndex::Id(entity_id) => { - storage::entity_model::read_model_entity(model_selector, entity_id, layout) - }, - ModelIndex::MemberId(( - entity_id, member_id - )) => { - storage::entity_model::read_model_member( - model_selector, entity_id, member_id, layout - ) - } - } + self.get_entity_internal(model_selector, index, layout) } - // set_entities_batch. (check acl once, set batch). + fn entities( + self: @ContractState, model_selector: felt252, indexes: Span, layout: Layout + ) -> Span> { + let mut models: Array> = array![]; + + for i in indexes { + models.append(self.get_entity_internal(model_selector, *i, layout)); + }; + + models.span() + } fn set_entity( ref self: ContractState, @@ -846,6 +872,39 @@ pub mod world { } } + fn set_entities( + ref self: ContractState, + model_selector: felt252, + indexes: Span, + values: Span>, + layout: Layout + ) { + if indexes.len() != values.len() { + panic_with_byte_array( + @errors::lengths_mismatch(@"indexes", @"values", @"set_entities") + ); + } + + if let Resource::Model((_, _)) = self.resources.read(model_selector) { + self.assert_caller_permissions(model_selector, Permission::Writer); + + let mut i = 0; + loop { + if i >= indexes.len() { + break; + } + + self.set_entity_internal(model_selector, *indexes[i], *values[i], layout); + + i += 1; + }; + } else { + panic_with_byte_array( + @errors::resource_conflict(@format!("{model_selector}"), @"model") + ); + } + } + fn delete_entity( ref self: ContractState, model_selector: felt252, index: ModelIndex, layout: Layout ) { @@ -859,6 +918,25 @@ pub mod world { } } + fn delete_entities( + ref self: ContractState, + model_selector: felt252, + indexes: Span, + layout: Layout + ) { + if let Resource::Model((_, _)) = self.resources.read(model_selector) { + self.assert_caller_permissions(model_selector, Permission::Writer); + + for i in indexes { + self.delete_entity_internal(model_selector, *i, layout); + } + } else { + panic_with_byte_array( + @errors::resource_conflict(@format!("{model_selector}"), @"model") + ); + } + } + fn resource(self: @ContractState, selector: felt252) -> Resource { self.resources.read(selector) } @@ -1102,6 +1180,34 @@ pub mod world { } } + /// Gets the model values for the given entity. + /// + /// # Arguments + /// + /// * `model_selector` - The selector of the model to be retrieved. + /// * `index` - The entity/member to read for the given model. + /// * `layout` - The memory layout of the model. + fn get_entity_internal( + self: @ContractState, model_selector: felt252, index: ModelIndex, layout: Layout + ) -> Span { + match index { + ModelIndex::Keys(keys) => { + let entity_id = entity_id_from_keys(keys); + storage::entity_model::read_model_entity(model_selector, entity_id, layout) + }, + ModelIndex::Id(entity_id) => { + storage::entity_model::read_model_entity(model_selector, entity_id, layout) + }, + ModelIndex::MemberId(( + entity_id, member_id + )) => { + storage::entity_model::read_model_member( + model_selector, entity_id, member_id, layout + ) + } + } + } + /// Returns the hash of the internal namespace for a dojo world. fn world_internal_namespace(self: @ContractState) -> (ByteArray, felt252) { let name = "__DOJO__"; diff --git a/crates/dojo/lang/src/attribute_macros/event.rs b/crates/dojo/lang/src/attribute_macros/event.rs index faef8ee2e0..aa8d7b8813 100644 --- a/crates/dojo/lang/src/attribute_macros/event.rs +++ b/crates/dojo/lang/src/attribute_macros/event.rs @@ -10,60 +10,20 @@ use cairo_lang_defs::plugin::{ DynGeneratedFileAuxData, PluginDiagnostic, PluginGeneratedFile, PluginResult, }; use cairo_lang_diagnostics::Severity; -use cairo_lang_syntax::node::ast::{ArgClauseNamed, Expr, ModuleItem}; +use cairo_lang_syntax::node::ast::ModuleItem; use cairo_lang_syntax::node::db::SyntaxGroup; use cairo_lang_syntax::node::helpers::QueryAttrs; -use cairo_lang_syntax::node::{ast, Terminal, TypedStablePtr, TypedSyntaxNode}; +use cairo_lang_syntax::node::{ast, TypedStablePtr, TypedSyntaxNode}; use cairo_lang_utils::unordered_hash_map::UnorderedHashMap; use dojo_types::naming; -use super::element::{ - parse_members, serialize_keys_and_values, CommonStructParameters, StructParameterParser, -}; +use super::element::{parse_members, serialize_keys_and_values}; use crate::aux_data::EventAuxData; use crate::derive_macros::{ extract_derive_attr_names, handle_derive_attrs, DOJO_INTROSPECT_DERIVE, DOJO_PACKED_DERIVE, }; const EVENT_PATCH: &str = include_str!("./patches/event.patch.cairo"); -use super::DOJO_EVENT_ATTR; - -pub const PARAMETER_HISTORICAL: &str = "historical"; -pub const DEFAULT_HISTORICAL_VALUE: bool = false; - -#[derive(Debug)] -struct EventParameters { - common: CommonStructParameters, - historical: bool, -} - -impl Default for EventParameters { - fn default() -> EventParameters { - EventParameters { - common: CommonStructParameters::default(), - historical: DEFAULT_HISTORICAL_VALUE, - } - } -} - -impl StructParameterParser for EventParameters { - fn process_named_parameters( - &mut self, - db: &dyn SyntaxGroup, - attribute_name: &str, - arg: ArgClauseNamed, - diagnostics: &mut Vec, - ) { - match arg.name(db).text(db).as_str() { - PARAMETER_HISTORICAL => { - self.historical = get_historical(attribute_name, arg.value(db), diagnostics); - } - _ => { - self.common.process_named_parameters(db, attribute_name, arg, diagnostics); - } - } - } -} #[derive(Debug, Clone, Default)] pub struct DojoEvent {} @@ -78,14 +38,6 @@ impl DojoEvent { /// * A RewriteNode containing the generated code. pub fn from_struct(db: &dyn SyntaxGroup, struct_ast: ast::ItemStruct) -> PluginResult { let mut diagnostics = vec![]; - let mut parameters = EventParameters::default(); - - parameters.load_from_struct( - db, - &DOJO_EVENT_ATTR.to_string(), - struct_ast.clone(), - &mut diagnostics, - ); let event_name = struct_ast.name(db).as_syntax_node().get_text(db).trim().to_string(); @@ -106,9 +58,6 @@ impl DojoEvent { } } - let event_version = parameters.common.version.to_string(); - let event_historical = parameters.historical.to_string(); - let members = parse_members(db, &struct_ast.members(db).elements(db), &mut diagnostics); let mut serialized_keys: Vec = vec![]; @@ -171,8 +120,6 @@ impl DojoEvent { ("member_names".to_string(), RewriteNode::new_modified(member_names)), ("serialized_keys".to_string(), RewriteNode::new_modified(serialized_keys)), ("serialized_values".to_string(), RewriteNode::new_modified(serialized_values)), - ("event_version".to_string(), RewriteNode::Text(event_version)), - ("event_historical".to_string(), RewriteNode::Text(event_historical)), ]), ); @@ -202,25 +149,3 @@ impl DojoEvent { } } } - -/// Get the historical boolean parameter from the `Expr` parameter. -fn get_historical( - attribute_name: &str, - arg_value: Expr, - diagnostics: &mut Vec, -) -> bool { - match arg_value { - Expr::True(_) => true, - Expr::False(_) => false, - _ => { - diagnostics.push(PluginDiagnostic { - message: format!( - "The argument '{PARAMETER_HISTORICAL}' of {attribute_name} must be a boolean", - ), - stable_ptr: arg_value.stable_ptr().untyped(), - severity: Severity::Error, - }); - DEFAULT_HISTORICAL_VALUE - } - } -} diff --git a/crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo b/crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo index 2c8cfe2b86..9612e9d056 100644 --- a/crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo +++ b/crates/dojo/lang/src/attribute_macros/patches/event.patch.cairo @@ -4,16 +4,10 @@ pub impl $type_name$DojoEventImpl of dojo::event::Event<$type_name$> { "$type_name$" } - #[inline(always)] - fn version() -> u8 { - $event_version$ - } - #[inline(always)] fn definition() -> dojo::event::EventDefinition { dojo::event::EventDefinition { name: Self::name(), - version: Self::version(), layout: Self::layout(), schema: Self::schema() } @@ -29,11 +23,6 @@ pub impl $type_name$DojoEventImpl of dojo::event::Event<$type_name$> { dojo::meta::introspect::Introspect::<$type_name$>::ty() } - #[inline(always)] - fn historical() -> bool { - $event_historical$ - } - #[inline(always)] fn keys(self: @$type_name$) -> Span { let mut serialized = core::array::ArrayTrait::new(); @@ -67,10 +56,6 @@ pub mod e_$type_name$ { "$type_name$" } - fn version(self: @ContractState) -> u8 { - $event_version$ - } - fn definition(self: @ContractState) -> dojo::event::EventDefinition { dojo::event::Event::<$type_name$>::definition() } @@ -83,4 +68,15 @@ pub mod e_$type_name$ { dojo::meta::introspect::Introspect::<$type_name$>::ty() } } + + #[abi(per_item)] + #[generate_trait] + impl $type_name$Impl of I$type_name${ + // Ensures the ABI contains the Event struct, since it's never used + // by systems directly. + #[external(v0)] + fn ensure_abi(self: @ContractState, event: $type_name$) { + let _event = event; + } + } } diff --git a/crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo b/crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo index c84376c600..7b5372dc10 100644 --- a/crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo +++ b/crates/dojo/lang/src/attribute_macros/patches/model.patch.cairo @@ -102,9 +102,3 @@ pub mod m_$model_type$ { } } } - -#[cfg(target: "test")] -pub impl $model_type$ModelTestImpl> = dojo::model::model::ModelTestImpl; - -#[cfg(target: "test")] -pub impl $model_type$ModelValueTestImpl> = dojo::model::model_value::ModelValueTestImpl; diff --git a/crates/dojo/world/src/contracts/abigen/world.rs b/crates/dojo/world/src/contracts/abigen/world.rs index 3c1dc23eca..bd07917a9f 100644 --- a/crates/dojo/world/src/contracts/abigen/world.rs +++ b/crates/dojo/world/src/contracts/abigen/world.rs @@ -202,7 +202,6 @@ impl ContractUpgraded { pub struct EventEmitted { pub selector: starknet::core::types::Felt, pub system_address: cainome::cairo_serde::ContractAddress, - pub historical: bool, pub keys: Vec, pub values: Vec, } @@ -215,7 +214,6 @@ impl cainome::cairo_serde::CairoSerde for EventEmitted { __size += starknet::core::types::Felt::cairo_serialized_size(&__rust.selector); __size += cainome::cairo_serde::ContractAddress::cairo_serialized_size(&__rust.system_address); - __size += bool::cairo_serialized_size(&__rust.historical); __size += Vec::::cairo_serialized_size(&__rust.keys); __size += Vec::::cairo_serialized_size(&__rust.values); __size @@ -225,7 +223,6 @@ impl cainome::cairo_serde::CairoSerde for EventEmitted { __out.extend(starknet::core::types::Felt::cairo_serialize(&__rust.selector)); __out .extend(cainome::cairo_serde::ContractAddress::cairo_serialize(&__rust.system_address)); - __out.extend(bool::cairo_serialize(&__rust.historical)); __out.extend(Vec::::cairo_serialize(&__rust.keys)); __out.extend(Vec::::cairo_serialize(&__rust.values)); __out @@ -240,13 +237,11 @@ impl cainome::cairo_serde::CairoSerde for EventEmitted { let system_address = cainome::cairo_serde::ContractAddress::cairo_deserialize(__felts, __offset)?; __offset += cainome::cairo_serde::ContractAddress::cairo_serialized_size(&system_address); - let historical = bool::cairo_deserialize(__felts, __offset)?; - __offset += bool::cairo_serialized_size(&historical); let keys = Vec::::cairo_deserialize(__felts, __offset)?; __offset += Vec::::cairo_serialized_size(&keys); let values = Vec::::cairo_deserialize(__felts, __offset)?; __offset += Vec::::cairo_serialized_size(&values); - Ok(EventEmitted { selector, system_address, historical, keys, values }) + Ok(EventEmitted { selector, system_address, keys, values }) } } impl EventEmitted { @@ -1732,16 +1727,6 @@ impl TryFrom<&starknet::core::types::EmittedEvent> for Event { }; key_offset += cainome::cairo_serde::ContractAddress::cairo_serialized_size(&system_address); - let historical = match bool::cairo_deserialize(&event.keys, key_offset) { - Ok(v) => v, - Err(e) => { - return Err(format!( - "Could not deserialize field {} for {}: {:?}", - "historical", "EventEmitted", e - )); - } - }; - key_offset += bool::cairo_serialized_size(&historical); let keys = match Vec::::cairo_deserialize( &event.data, data_offset, @@ -1771,7 +1756,6 @@ impl TryFrom<&starknet::core::types::EmittedEvent> for Event { return Ok(Event::EventEmitted(EventEmitted { selector, system_address, - historical, keys, values, })); @@ -2612,16 +2596,6 @@ impl TryFrom<&starknet::core::types::Event> for Event { }; key_offset += cainome::cairo_serde::ContractAddress::cairo_serialized_size(&system_address); - let historical = match bool::cairo_deserialize(&event.keys, key_offset) { - Ok(v) => v, - Err(e) => { - return Err(format!( - "Could not deserialize field {} for {}: {:?}", - "historical", "EventEmitted", e - )); - } - }; - key_offset += bool::cairo_serialized_size(&historical); let keys = match Vec::::cairo_deserialize( &event.data, data_offset, @@ -2651,7 +2625,6 @@ impl TryFrom<&starknet::core::types::Event> for Event { return Ok(Event::EventEmitted(EventEmitted { selector, system_address, - historical, keys, values, })); @@ -3252,6 +3225,26 @@ impl cainome::cairo_serde::CairoSerde for Resource { } } impl WorldContract { + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] + pub fn entities( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + layout: &Layout, + ) -> cainome::cairo_serde::call::FCall>> { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Layout::cairo_serialize(layout)); + let __call = starknet::core::types::FunctionCall { + contract_address: self.address, + entry_point_selector: starknet::macros::selector!("entities"), + calldata: __calldata, + }; + cainome::cairo_serde::call::FCall::new(__call, self.provider()) + } #[allow(clippy::ptr_arg)] #[allow(clippy::too_many_arguments)] pub fn entity( @@ -3342,6 +3335,45 @@ impl WorldContract { } #[allow(clippy::ptr_arg)] #[allow(clippy::too_many_arguments)] + pub fn delete_entities_getcall( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + layout: &Layout, + ) -> starknet::core::types::Call { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Layout::cairo_serialize(layout)); + starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("delete_entities"), + calldata: __calldata, + } + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] + pub fn delete_entities( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + layout: &Layout, + ) -> starknet::accounts::ExecutionV1 { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Layout::cairo_serialize(layout)); + let __call = starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("delete_entities"), + calldata: __calldata, + }; + self.account.execute_v1(vec![__call]) + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] pub fn delete_entity_getcall( &self, model_selector: &starknet::core::types::Felt, @@ -3386,14 +3418,12 @@ impl WorldContract { event_selector: &starknet::core::types::Felt, keys: &Vec, values: &Vec, - historical: &bool, ) -> starknet::core::types::Call { use cainome::cairo_serde::CairoSerde; let mut __calldata = vec![]; __calldata.extend(starknet::core::types::Felt::cairo_serialize(event_selector)); __calldata.extend(Vec::::cairo_serialize(keys)); __calldata.extend(Vec::::cairo_serialize(values)); - __calldata.extend(bool::cairo_serialize(historical)); starknet::core::types::Call { to: self.address, selector: starknet::macros::selector!("emit_event"), @@ -3407,14 +3437,12 @@ impl WorldContract { event_selector: &starknet::core::types::Felt, keys: &Vec, values: &Vec, - historical: &bool, ) -> starknet::accounts::ExecutionV1 { use cainome::cairo_serde::CairoSerde; let mut __calldata = vec![]; __calldata.extend(starknet::core::types::Felt::cairo_serialize(event_selector)); __calldata.extend(Vec::::cairo_serialize(keys)); __calldata.extend(Vec::::cairo_serialize(values)); - __calldata.extend(bool::cairo_serialize(historical)); let __call = starknet::core::types::Call { to: self.address, selector: starknet::macros::selector!("emit_event"), @@ -3424,6 +3452,45 @@ impl WorldContract { } #[allow(clippy::ptr_arg)] #[allow(clippy::too_many_arguments)] + pub fn emit_events_getcall( + &self, + event_selector: &starknet::core::types::Felt, + keys: &Vec>, + values: &Vec>, + ) -> starknet::core::types::Call { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(event_selector)); + __calldata.extend(Vec::>::cairo_serialize(keys)); + __calldata.extend(Vec::>::cairo_serialize(values)); + starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("emit_events"), + calldata: __calldata, + } + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] + pub fn emit_events( + &self, + event_selector: &starknet::core::types::Felt, + keys: &Vec>, + values: &Vec>, + ) -> starknet::accounts::ExecutionV1 { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(event_selector)); + __calldata.extend(Vec::>::cairo_serialize(keys)); + __calldata.extend(Vec::>::cairo_serialize(values)); + let __call = starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("emit_events"), + calldata: __calldata, + }; + self.account.execute_v1(vec![__call]) + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] pub fn grant_owner_getcall( &self, resource: &starknet::core::types::Felt, @@ -3739,6 +3806,49 @@ impl WorldContract { } #[allow(clippy::ptr_arg)] #[allow(clippy::too_many_arguments)] + pub fn set_entities_getcall( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + values: &Vec>, + layout: &Layout, + ) -> starknet::core::types::Call { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Vec::>::cairo_serialize(values)); + __calldata.extend(Layout::cairo_serialize(layout)); + starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("set_entities"), + calldata: __calldata, + } + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] + pub fn set_entities( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + values: &Vec>, + layout: &Layout, + ) -> starknet::accounts::ExecutionV1 { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Vec::>::cairo_serialize(values)); + __calldata.extend(Layout::cairo_serialize(layout)); + let __call = starknet::core::types::Call { + to: self.address, + selector: starknet::macros::selector!("set_entities"), + calldata: __calldata, + }; + self.account.execute_v1(vec![__call]) + } + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] pub fn set_entity_getcall( &self, model_selector: &starknet::core::types::Felt, @@ -3966,6 +4076,26 @@ impl WorldContract { } } impl WorldContractReader

{ + #[allow(clippy::ptr_arg)] + #[allow(clippy::too_many_arguments)] + pub fn entities( + &self, + model_selector: &starknet::core::types::Felt, + indexes: &Vec, + layout: &Layout, + ) -> cainome::cairo_serde::call::FCall>> { + use cainome::cairo_serde::CairoSerde; + let mut __calldata = vec![]; + __calldata.extend(starknet::core::types::Felt::cairo_serialize(model_selector)); + __calldata.extend(Vec::::cairo_serialize(indexes)); + __calldata.extend(Layout::cairo_serialize(layout)); + let __call = starknet::core::types::FunctionCall { + contract_address: self.address, + entry_point_selector: starknet::macros::selector!("entities"), + calldata: __calldata, + }; + cainome::cairo_serde::call::FCall::new(__call, self.provider()) + } #[allow(clippy::ptr_arg)] #[allow(clippy::too_many_arguments)] pub fn entity( diff --git a/crates/torii/core/src/processors/event_message.rs b/crates/torii/core/src/processors/event_message.rs index ec52d5b698..6236cda856 100644 --- a/crates/torii/core/src/processors/event_message.rs +++ b/crates/torii/core/src/processors/event_message.rs @@ -71,7 +71,9 @@ where let mut entity = model.schema.clone(); entity.deserialize(&mut keys_and_unpacked)?; - db.set_event_message(entity, event_id, block_timestamp, event.historical).await?; + // TODO: this must come from some torii's configuration. + let historical = false; + db.set_event_message(entity, event_id, block_timestamp, historical).await?; Ok(()) } } diff --git a/crates/torii/types-test/src/contracts.cairo b/crates/torii/types-test/src/contracts.cairo index 71a979a4e8..92d5aad27e 100644 --- a/crates/torii/types-test/src/contracts.cairo +++ b/crates/torii/types-test/src/contracts.cairo @@ -15,7 +15,7 @@ mod records { use dojo::world::IWorldDispatcherTrait; use super::IRecords; - #[derive(Drop, starknet::Event)] + #[derive(Drop, Serde, starknet::Event)] #[dojo::event] struct RecordLogged { #[key] diff --git a/examples/spawn-and-move/dojo_dev.toml b/examples/spawn-and-move/dojo_dev.toml index 9a1aea6910..9f43e93467 100644 --- a/examples/spawn-and-move/dojo_dev.toml +++ b/examples/spawn-and-move/dojo_dev.toml @@ -11,7 +11,7 @@ rpc_url = "http://localhost:5050/" # Default account for katana with seed = 0 account_address = "0x2af9427c5a277474c079a1283c880ee8a6f0f8fbf73ce969c08d88befec1bba" private_key = "0x1800000000300000180000000000030000000000003006001800006600" -world_address = "0xecd610a15ce418719008d506c662ec3e420cf17b4b6d086e53281f30425115" +world_address = "0x4bf1624ebc515bc20b8a7c4c2f669872cd61e3abab0cc77d9b9c91fcce11bdc" [init_call_args] "ns-others" = ["0xff"] diff --git a/spawn-and-move-db.tar.gz b/spawn-and-move-db.tar.gz index 5fa4eaf327..d9edf8ac20 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 f23aa96f44..d20aa96eb8 100644 Binary files a/types-test-db.tar.gz and b/types-test-db.tar.gz differ