From 0e935fb34ef9e2a967361dd61bff76a439ce7f39 Mon Sep 17 00:00:00 2001 From: gianalarcon Date: Mon, 15 Jan 2024 00:22:27 -0500 Subject: [PATCH] feat: Improve fn delete_entity(), add event StoreDelRecordProcessor --- crates/dojo-core/src/world.cairo | 23 ++++++++-------- .../core/src/processors/store_del_record.rs | 13 +++++++++ crates/torii/core/src/sql.rs | 27 ++++++++++++++----- crates/torii/server/src/cli.rs | 2 ++ crates/torii/types-test/Scarb.lock | 2 +- examples/spawn-and-move/Scarb.lock | 2 +- examples/spawn-and-move/src/actions.cairo | 13 ++++++--- 7 files changed, 58 insertions(+), 24 deletions(-) diff --git a/crates/dojo-core/src/world.cairo b/crates/dojo-core/src/world.cairo index 1271a3a621..f81e04530a 100644 --- a/crates/dojo-core/src/world.cairo +++ b/crates/dojo-core/src/world.cairo @@ -47,7 +47,7 @@ trait IWorld { #[starknet::interface] trait IUpgradeableWorld { - fn upgrade(ref self: T, new_class_hash : ClassHash); + fn upgrade(ref self: T, new_class_hash: ClassHash); } #[starknet::interface] @@ -70,15 +70,15 @@ mod world { use starknet::{ get_caller_address, get_contract_address, get_tx_info, contract_address::ContractAddressIntoFelt252, ClassHash, Zeroable, ContractAddress, - syscalls::{deploy_syscall, emit_event_syscall, replace_class_syscall}, SyscallResult, SyscallResultTrait, - SyscallResultTraitImpl + syscalls::{deploy_syscall, emit_event_syscall, replace_class_syscall}, SyscallResult, + SyscallResultTrait, SyscallResultTraitImpl }; use dojo::database; use dojo::database::index::WhereCondition; use dojo::executor::{IExecutorDispatcher, IExecutorDispatcherTrait}; use dojo::world::{IWorldDispatcher, IWorld, IUpgradeableWorld}; - + use dojo::components::upgradeable::{IUpgradeableDispatcher, IUpgradeableDispatcherTrait}; const NAME_ENTRYPOINT: felt252 = @@ -112,7 +112,7 @@ mod world { struct WorldUpgraded { class_hash: ClassHash, } - + #[derive(Drop, starknet::Event)] struct ContractDeployed { salt: felt252, @@ -525,7 +525,7 @@ mod world { }; let key = poseidon::poseidon_hash_span(keys); - database::set(model, key, 0, empty_values.span(), layout); + //database::set(model, key, 0, empty_values.span(), layout); // this deletes the index database::del(model, key); @@ -641,17 +641,18 @@ mod world { /// # Arguments /// /// * `new_class_hash` - The new world class hash. - fn upgrade(ref self: ContractState, new_class_hash : ClassHash){ + fn upgrade(ref self: ContractState, new_class_hash: ClassHash) { assert(new_class_hash.is_non_zero(), 'invalid class_hash'); - assert(IWorld::is_owner(@self, get_tx_info().unbox().account_contract_address, WORLD), 'only owner can upgrade'); + assert( + IWorld::is_owner(@self, get_tx_info().unbox().account_contract_address, WORLD), + 'only owner can upgrade' + ); // upgrade to new_class_hash replace_class_syscall(new_class_hash).unwrap(); // emit Upgrade Event - EventEmitter::emit( - ref self, WorldUpgraded {class_hash: new_class_hash } - ); + EventEmitter::emit(ref self, WorldUpgraded { class_hash: new_class_hash }); } } diff --git a/crates/torii/core/src/processors/store_del_record.rs b/crates/torii/core/src/processors/store_del_record.rs index 0bb243b827..d80c4ec8f8 100644 --- a/crates/torii/core/src/processors/store_del_record.rs +++ b/crates/torii/core/src/processors/store_del_record.rs @@ -51,9 +51,22 @@ where let model = db.model(&name).await?; + let keys_start = NUM_KEYS_INDEX + 1; + let keys_end: usize = keys_start + usize::from(u8::try_from(event.data[NUM_KEYS_INDEX])?); + let keys = event.data[keys_start..keys_end].to_vec(); + + let values_start = keys_end + 2; + let values_end: usize = values_start + usize::from(u8::try_from(event.data[keys_end + 1])?); + + let values = event.data[values_start..values_end].to_vec(); + let mut keys_and_unpacked = [keys, values].concat(); + let mut entity = model.schema().await?; + info!("get entity"); + entity.deserialize(&mut keys_and_unpacked)?; db.delete_entity(entity, event_id).await?; + info!("Deleted entity"); Ok(()) } } diff --git a/crates/torii/core/src/sql.rs b/crates/torii/core/src/sql.rs index c894decc5e..7f70916a51 100644 --- a/crates/torii/core/src/sql.rs +++ b/crates/torii/core/src/sql.rs @@ -6,6 +6,7 @@ use chrono::Utc; use dojo_types::primitive::Primitive; use dojo_types::schema::Ty; use dojo_world::metadata::WorldMetadata; +use log::info; use sqlx::pool::PoolConnection; use sqlx::{Pool, Sqlite}; use starknet::core::types::{Event, FieldElement, InvokeTransactionV1}; @@ -149,13 +150,25 @@ impl Sql { Ok(()) } - pub fn delete_entity(&mut self, model: String, key: FieldElement) { - println!("delete entity model: {}", model); - let model = Argument::String(model); - println!("delete entity key: {:#x}", key); - let id = Argument::FieldElement(key); - - self.query_queue.enqueue("DELETE FROM ? WHERE id = ?", vec![model, id]); + pub async fn delete_entity(&mut self, entity: Ty, event_id: &str) -> Result<()> { + let keys = if let Ty::Struct(s) = &entity { + let mut keys = Vec::new(); + for m in s.keys() { + keys.extend(m.serialize()?); + } + keys + } else { + return Err(anyhow!("Entity is not a struct")); + }; + let entity_id = format!("{:#x}", poseidon_hash_many(&keys)); + let table = format!("{}", entity.name()); + info!("Deleting entity: {}, table: {}", entity_id, table); + self.query_queue.enqueue( + "DELETE FROM ? WHERE entity_id = ?", + vec![Argument::String(table), Argument::String(entity_id)], + ); + self.query_queue.execute_all().await.unwrap(); + Ok(()) } pub fn set_metadata(&mut self, resource: &FieldElement, uri: &str) { diff --git a/crates/torii/server/src/cli.rs b/crates/torii/server/src/cli.rs index 4858ad2265..c2ebe79f7c 100644 --- a/crates/torii/server/src/cli.rs +++ b/crates/torii/server/src/cli.rs @@ -31,6 +31,7 @@ use tokio_stream::StreamExt; use torii_core::engine::{Engine, EngineConfig, Processors}; use torii_core::processors::metadata_update::MetadataUpdateProcessor; use torii_core::processors::register_model::RegisterModelProcessor; +use torii_core::processors::store_del_record::StoreDelRecordProcessor; use torii_core::processors::store_set_record::StoreSetRecordProcessor; use torii_core::processors::store_transaction::StoreTransactionProcessor; use torii_core::simple_broker::SimpleBroker; @@ -132,6 +133,7 @@ async fn main() -> anyhow::Result<()> { Box::new(RegisterModelProcessor), Box::new(StoreSetRecordProcessor), Box::new(MetadataUpdateProcessor), + Box::new(StoreDelRecordProcessor), ], transaction: vec![Box::new(StoreTransactionProcessor)], ..Processors::default() diff --git a/crates/torii/types-test/Scarb.lock b/crates/torii/types-test/Scarb.lock index 5cb79dfe8e..86f181d66b 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.4.4" +version = "0.5.0" dependencies = [ "dojo", ] diff --git a/examples/spawn-and-move/Scarb.lock b/examples/spawn-and-move/Scarb.lock index b61ff06a70..ae8ad6f337 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.4.4" +version = "0.5.0" dependencies = [ "dojo", ] diff --git a/examples/spawn-and-move/src/actions.cairo b/examples/spawn-and-move/src/actions.cairo index e6fc4ce674..402e601c60 100644 --- a/examples/spawn-and-move/src/actions.cairo +++ b/examples/spawn-and-move/src/actions.cairo @@ -6,7 +6,7 @@ use starknet::{ContractAddress, ClassHash}; trait IActions { fn spawn(self: @TContractState); fn move(self: @TContractState, direction: Direction); - fn delete(self: @TContractState); + fn delete_move(self: @TContractState); } #[dojo::contract] @@ -88,7 +88,7 @@ mod actions { return (); } - fn delete(self: @ContractState) { + fn delete_move(self: @ContractState) { // Access the world dispatcher for reading. let world = self.world_dispatcher.read(); @@ -96,10 +96,10 @@ mod actions { let player = get_caller_address(); // Retrieve the player's current position and moves data from the world. - let (position, moves) = get!(world, player, (Position, Moves)); + let moves = get!(world, player, Moves); // Delete the player's data from the world. - delete!(world, (position, moves)); + delete!(world, (moves)); } } } @@ -144,5 +144,10 @@ mod tests { let new_position = get!(world, caller, Position); assert(new_position.vec.x == 11, 'position x is wrong'); assert(new_position.vec.y == 10, 'position y is wrong'); + + actions_system.delete_move(); + // check world state + let moves = get!(world, caller, Moves); + assert(moves.remaining == 0, 'moves is wrong'); } }