From a123adc48e4e1d6146e893668c085400f4c372a9 Mon Sep 17 00:00:00 2001 From: glihm Date: Tue, 12 Sep 2023 20:08:20 -0600 Subject: [PATCH] add event manager logic --- src/main.rs | 25 ++++++--- src/managers/event_manager.rs | 96 +++++++++++++++++++++++------------ src/transfer.rs | 54 ++++++++++---------- 3 files changed, 110 insertions(+), 65 deletions(-) diff --git a/src/main.rs b/src/main.rs index 91aa62b6d..be4d3b5b1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,7 +28,7 @@ async fn main() -> Result<()> { let sn_client = StarknetClient::new(&rpc_provider.clone())?; let storage = storage::init_default(); let block_manager = BlockManager::new(&storage, &sn_client); - let event_manager = EventManager::new(&storage, &sn_client); + let mut event_manager = EventManager::new(&storage, &sn_client); let mut collection_manager = CollectionManager::new(&storage, &sn_client); let (from_block, to_block, poll_head_of_chain) = block_manager.get_block_range(); @@ -48,6 +48,8 @@ async fn main() -> Result<()> { continue; } + let block_ts = sn_client.block_time(BlockId::Number(current_u64)).await?; + let blocks_events = sn_client .fetch_events( BlockId::Number(current_u64), @@ -69,17 +71,28 @@ async fn main() -> Result<()> { } }; + let contract_type = contract_info.r#type; + if contract_type == ContractType::Other { + continue; + } + log::debug!( "Contract type [{:#064x}] : {}", contract_address, - contract_info.r#type.to_string() + contract_type.to_string() ); - if contract_info.r#type == ContractType::Other { - continue; - } + let _token_id = match event_manager + .format_event(&e, contract_type, block_ts) + .await + { + Ok(token_id) => token_id, + Err(err) => { + log::error!("Can't format event {:?}\nevent: {:?}", err, e); + continue; + } + }; - // event_manager.identify_event(e, block_timestamp, contract_info); // token_manager.register_token(...); } } diff --git a/src/managers/event_manager.rs b/src/managers/event_manager.rs index a10f8694a..bcd2b0786 100644 --- a/src/managers/event_manager.rs +++ b/src/managers/event_manager.rs @@ -1,3 +1,4 @@ +use crate::ContractType; use anyhow::{anyhow, Result}; use ark_starknet::client2::StarknetClient; use ark_storage::storage_manager::StorageManager; @@ -9,6 +10,8 @@ use starknet::macros::selector; #[derive(Debug)] pub struct EventManager<'a, T: StorageManager> { storage: &'a T, + // I am not sure we gain a lot by having it here. As a temporary + // value will be on the stack, which is way faster that accessing the heap. token_event: TokenEvent, client: &'a StarknetClient, } @@ -28,57 +31,86 @@ impl<'a, T: StorageManager> EventManager<'a, T> { return Some(vec![vec![selector!("Transfer")]]); } - pub fn reset_event(&mut self) { - self.token_event = TokenEvent::default(); - } - - pub fn format_event( + /// Formats a token event based on the event content. + /// Returns the token_id if the event were identified, + /// an Err otherwise. + pub async fn format_event( &mut self, event: &EmittedEvent, - contract_type: &str, + contract_type: ContractType, timestamp: u64, - ) -> Result<()> { - if event.data.len() < 4 { - return Err(anyhow!("Invalid event data")); - } + ) -> Result { + self.reset_event(); + + // As cairo didn't have keys before, we first check if the data + // contains the info. If not, we check into the keys, skipping the first + // element which is the selector. + let event_info = if let Some(d_info) = Self::get_event_info_from_felts(&event.data) { + d_info + } else if let Some(k_info) = Self::get_event_info_from_felts(&event.keys[1..]) { + k_info + } else { + log::warn!("Can't find event data into this event"); + return Err(anyhow!("Can't format event")); + }; + + let (from, to, token_id) = event_info; - self.token_event.from_address_field_element = event.data[0]; - self.token_event.from_address = format!("{:#064x}", event.data[0]); - self.token_event.to_address_field_element = event.data[1]; - self.token_event.to_address = format!("{:#064x}", event.data[1]); + // TODO: why do we need this entry 2 times for the felt and the string? + self.token_event.from_address_field_element = from; + self.token_event.from_address = format!("{:#064x}", from); + self.token_event.to_address_field_element = to; + self.token_event.to_address = format!("{:#064x}", to); self.token_event.contract_address = format!("{:#064x}", event.from_address); self.token_event.transaction_hash = format!("{:#064x}", event.transaction_hash); - self.token_event.token_id = TokenId { - low: event.data[2], - high: event.data[3], - }; + self.token_event.token_id = token_id.clone(); self.token_event.formated_token_id = self.token_event.token_id.format(); self.token_event.block_number = event.block_number; self.token_event.timestamp = timestamp; self.token_event.contract_type = contract_type.to_string(); - self.token_event.event_type = self.get_event_type(); - Ok(()) - } + self.token_event.event_type = Self::get_event_type(from, to); - pub fn get_event(&self) -> &TokenEvent { - &self.token_event + info!("Event identified: {:?}", self.token_event.event_type); + + // TODO: self.storage.register_event(self.token_event); + // TODO: check depending on event type if it's a create/update etc...? + + Ok(token_id) } - pub fn get_event_type(&mut self) -> EventType { - if self.token_event.from_address_field_element == FieldElement::ZERO { - info!("EVENT MANAGER: Mint detected"); + pub fn get_event_type(from: FieldElement, to: FieldElement) -> EventType { + if from == FieldElement::ZERO { EventType::Mint - } else if self.token_event.to_address_field_element == FieldElement::ZERO { - info!("EVENT MANAGER: Burn detected"); + } else if to == FieldElement::ZERO { EventType::Burn } else { - info!("EVENT MANAGER: Transfer detected"); EventType::Transfer } } - pub fn create_event(&self) -> Result<()> { - self.storage.create_event(&self.token_event); - Ok(()) + /// Returns the event info from vector of felts. + /// Event info are (from, to, token_id). + /// + /// This methods considers that the info of the + /// event is starting at index 0 of the input vector. + fn get_event_info_from_felts( + felts: &[FieldElement], + ) -> Option<(FieldElement, FieldElement, TokenId)> { + if felts.len() < 4 { + return None; + } + let from = felts[0]; + let to = felts[1]; + + let token_id = TokenId { + low: felts[2], + high: felts[3], + }; + + Some((from, to, token_id)) + } + + fn reset_event(&mut self) { + self.token_event = TokenEvent::default(); } } diff --git a/src/transfer.rs b/src/transfer.rs index 07439b11f..69ae8aa88 100644 --- a/src/transfer.rs +++ b/src/transfer.rs @@ -1,31 +1,31 @@ -use crate::managers::event_manager::EventManager; -use crate::managers::token_manager::TokenManager; -use anyhow::Result; -use ark_storage::storage_manager::StorageManager; -use ark_storage::types::EventType; -use starknet::core::types::EmittedEvent; +// use crate::managers::event_manager::EventManager; +// use crate::managers::token_manager::TokenManager; +// use anyhow::Result; +// use ark_storage::storage_manager::StorageManager; +// use ark_storage::types::EventType; +// use starknet::core::types::EmittedEvent; -pub async fn process_transfer<'a, T: StorageManager>( - event: &EmittedEvent, - contract_type: &str, - timestamp: u64, - token_manager: &mut TokenManager<'a, T>, - event_manager: &mut EventManager<'a, T>, -) -> Result<()> { - event_manager.format_event(event, contract_type, timestamp)?; - event_manager.create_event()?; +// pub async fn process_transfer<'a, T: StorageManager>( +// event: &EmittedEvent, +// contract_type: &str, +// timestamp: u64, +// token_manager: &mut TokenManager<'a, T>, +// event_manager: &mut EventManager<'a, T>, +// ) -> Result<()> { +// event_manager.format_event(event, contract_type, timestamp)?; +// event_manager.create_event()?; - let token_event = event_manager.get_event(); - token_manager.format_token_from_event(token_event); +// let token_event = event_manager.get_event(); +// token_manager.format_token_from_event(token_event); - if token_event.event_type == EventType::Mint { - token_manager.create_token()?; - } else { - // TODO update token owner - // token_manager.update_token_owner()?; - } +// if token_event.event_type == EventType::Mint { +// token_manager.create_token()?; +// } else { +// // TODO update token owner +// // token_manager.update_token_owner()?; +// } - token_manager.reset_token(); - event_manager.reset_event(); - Ok(()) -} +// token_manager.reset_token(); +// event_manager.reset_event(); +// Ok(()) +// }