diff --git a/crates/torii/core/src/engine.rs b/crates/torii/core/src/engine.rs index b8f398f135..f616ee64fb 100644 --- a/crates/torii/core/src/engine.rs +++ b/crates/torii/core/src/engine.rs @@ -610,6 +610,8 @@ impl Engine

{ let mut unique_contracts = HashSet::new(); // Contract -> Cursor for (event_idx, event) in events.iter().enumerate() { + // NOTE: erc* processors expect the event_id to be in this format to get + // transaction_hash: let event_id = format!("{:#064x}:{:#x}:{:#04x}", block_number, transaction_hash, event_idx); @@ -681,6 +683,8 @@ impl Engine

{ unique_contracts.insert(event.from_address); + // NOTE: erc* processors expect the event_id to be in this format to get + // transaction_hash: let event_id = format!("{:#064x}:{:#x}:{:#04x}", block_number, *transaction_hash, event_idx); @@ -899,3 +903,8 @@ where MaybePendingBlockWithTxHashes::PendingBlock(block) => Ok(block.timestamp), } } + +// event_id format: block_number:transaction_hash:event_idx +pub(crate) fn get_transaction_hash_from_event_id(event_id: &str) -> String { + event_id.split(':').nth(1).unwrap().to_string() +} diff --git a/crates/torii/core/src/processors/erc20_legacy_transfer.rs b/crates/torii/core/src/processors/erc20_legacy_transfer.rs index 4cef0dc19d..138ed79f19 100644 --- a/crates/torii/core/src/processors/erc20_legacy_transfer.rs +++ b/crates/torii/core/src/processors/erc20_legacy_transfer.rs @@ -7,6 +7,7 @@ use starknet::providers::Provider; use tracing::debug; use super::EventProcessor; +use crate::engine::get_transaction_hash_from_event_id; use crate::sql::Sql; pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc20_legacy_transfer"; @@ -40,18 +41,27 @@ where db: &mut Sql, _block_number: u64, block_timestamp: u64, - _event_id: &str, + event_id: &str, event: &Event, ) -> Result<(), Error> { let token_address = event.from_address; let from = event.data[0]; let to = event.data[1]; + let transaction_hash = get_transaction_hash_from_event_id(event_id); let value = U256Cainome::cairo_deserialize(&event.data, 2)?; let value = U256::from_words(value.low, value.high); - db.handle_erc20_transfer(token_address, from, to, value, world.provider(), block_timestamp) - .await?; + db.handle_erc20_transfer( + token_address, + from, + to, + value, + world.provider(), + block_timestamp, + &transaction_hash, + ) + .await?; debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "Legacy ERC20 Transfer"); Ok(()) diff --git a/crates/torii/core/src/processors/erc20_transfer.rs b/crates/torii/core/src/processors/erc20_transfer.rs index 10022d9eb0..895c4b8427 100644 --- a/crates/torii/core/src/processors/erc20_transfer.rs +++ b/crates/torii/core/src/processors/erc20_transfer.rs @@ -7,6 +7,7 @@ use starknet::providers::Provider; use tracing::debug; use super::EventProcessor; +use crate::engine::get_transaction_hash_from_event_id; use crate::sql::Sql; pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc20_transfer"; @@ -40,7 +41,7 @@ where db: &mut Sql, _block_number: u64, block_timestamp: u64, - _event_id: &str, + event_id: &str, event: &Event, ) -> Result<(), Error> { let token_address = event.from_address; @@ -49,9 +50,18 @@ where let value = U256Cainome::cairo_deserialize(&event.data, 0)?; let value = U256::from_words(value.low, value.high); + let transaction_hash = get_transaction_hash_from_event_id(event_id); - db.handle_erc20_transfer(token_address, from, to, value, world.provider(), block_timestamp) - .await?; + db.handle_erc20_transfer( + token_address, + from, + to, + value, + world.provider(), + block_timestamp, + &transaction_hash, + ) + .await?; debug!(target: LOG_TARGET,from = ?from, to = ?to, value = ?value, "ERC20 Transfer"); Ok(()) diff --git a/crates/torii/core/src/processors/erc721_legacy_transfer.rs b/crates/torii/core/src/processors/erc721_legacy_transfer.rs index 89a88f04a3..c38957516c 100644 --- a/crates/torii/core/src/processors/erc721_legacy_transfer.rs +++ b/crates/torii/core/src/processors/erc721_legacy_transfer.rs @@ -7,6 +7,7 @@ use starknet::providers::Provider; use tracing::debug; use super::EventProcessor; +use crate::engine::get_transaction_hash_from_event_id; use crate::sql::Sql; pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc721_legacy_transfer"; @@ -40,7 +41,7 @@ where db: &mut Sql, _block_number: u64, block_timestamp: u64, - _event_id: &str, + event_id: &str, event: &Event, ) -> Result<(), Error> { let token_address = event.from_address; @@ -49,6 +50,7 @@ where let token_id = U256Cainome::cairo_deserialize(&event.data, 2)?; let token_id = U256::from_words(token_id.low, token_id.high); + let transaction_hash = get_transaction_hash_from_event_id(event_id); db.handle_erc721_transfer( token_address, @@ -57,6 +59,7 @@ where token_id, world.provider(), block_timestamp, + &transaction_hash, ) .await?; debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer"); diff --git a/crates/torii/core/src/processors/erc721_transfer.rs b/crates/torii/core/src/processors/erc721_transfer.rs index 319ea81833..c55e700725 100644 --- a/crates/torii/core/src/processors/erc721_transfer.rs +++ b/crates/torii/core/src/processors/erc721_transfer.rs @@ -7,6 +7,7 @@ use starknet::providers::Provider; use tracing::debug; use super::EventProcessor; +use crate::engine::get_transaction_hash_from_event_id; use crate::sql::Sql; pub(crate) const LOG_TARGET: &str = "torii_core::processors::erc721_transfer"; @@ -40,7 +41,7 @@ where db: &mut Sql, _block_number: u64, block_timestamp: u64, - _event_id: &str, + event_id: &str, event: &Event, ) -> Result<(), Error> { let token_address = event.from_address; @@ -49,6 +50,7 @@ where let token_id = U256Cainome::cairo_deserialize(&event.keys, 3)?; let token_id = U256::from_words(token_id.low, token_id.high); + let transaction_hash = get_transaction_hash_from_event_id(event_id); db.handle_erc721_transfer( token_address, @@ -57,6 +59,7 @@ where token_id, world.provider(), block_timestamp, + &transaction_hash, ) .await?; debug!(target: LOG_TARGET, from = ?from, to = ?to, token_id = ?token_id, "ERC721 Transfer"); diff --git a/crates/torii/core/src/sql/erc.rs b/crates/torii/core/src/sql/erc.rs index 36bf6216f6..4dea567af7 100644 --- a/crates/torii/core/src/sql/erc.rs +++ b/crates/torii/core/src/sql/erc.rs @@ -25,6 +25,7 @@ impl Sql { amount: U256, provider: &P, block_timestamp: u64, + transaction_hash: &str, ) -> Result<()> { // contract_address let token_id = felt_to_sql_string(&contract_address); @@ -43,6 +44,7 @@ impl Sql { amount, &token_id, block_timestamp, + transaction_hash, )?; if from_address != Felt::ZERO { @@ -79,6 +81,7 @@ impl Sql { token_id: U256, provider: &P, block_timestamp: u64, + transaction_hash: &str, ) -> Result<()> { // contract_address:id let token_id = felt_and_u256_to_sql_string(&contract_address, &token_id); @@ -96,6 +99,7 @@ impl Sql { U256::from(1u8), &token_id, block_timestamp, + transaction_hash, )?; // from_address/contract_address:id @@ -307,6 +311,7 @@ impl Sql { Ok(()) } + #[allow(clippy::too_many_arguments)] fn store_erc_transfer_event( &mut self, contract_address: Felt, @@ -315,9 +320,11 @@ impl Sql { amount: U256, token_id: &str, block_timestamp: u64, + transaction_hash: &str, ) -> Result<()> { let insert_query = "INSERT INTO erc_transfers (contract_address, from_address, \ - to_address, amount, token_id, executed_at) VALUES (?, ?, ?, ?, ?, ?)"; + to_address, amount, token_id, executed_at, transaction_hash) VALUES \ + (?, ?, ?, ?, ?, ?, ?)"; self.executor.send(QueryMessage::other( insert_query.to_string(), @@ -328,6 +335,7 @@ impl Sql { Argument::String(u256_to_sql_string(&amount)), Argument::String(token_id.to_string()), Argument::String(utc_dt_string_from_timestamp(block_timestamp)), + Argument::String(transaction_hash.to_string()), ], ))?; diff --git a/crates/torii/graphql/src/mapping.rs b/crates/torii/graphql/src/mapping.rs index d871a1c71f..089d2a6b51 100644 --- a/crates/torii/graphql/src/mapping.rs +++ b/crates/torii/graphql/src/mapping.rs @@ -146,25 +146,26 @@ lazy_static! { ]); pub static ref ERC_BALANCE_TYPE_MAPPING: TypeMapping = IndexMap::from([ - (Name::new("balance"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("type"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("tokenMetadata"), TypeData::Simple(TypeRef::named(ERC_TOKEN_TYPE_NAME))), + (Name::new("balance"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("type"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("tokenMetadata"), TypeData::Simple(TypeRef::named_nn(ERC_TOKEN_TYPE_NAME))), ]); pub static ref ERC_TRANSFER_TYPE_MAPPING: TypeMapping = IndexMap::from([ - (Name::new("from"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("to"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("amount"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("type"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("executedAt"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("tokenMetadata"), TypeData::Simple(TypeRef::named(ERC_TOKEN_TYPE_NAME))), + (Name::new("from"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("to"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("amount"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("type"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("executedAt"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("tokenMetadata"), TypeData::Simple(TypeRef::named_nn(ERC_TOKEN_TYPE_NAME))), + (Name::new("transactionHash"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), ]); pub static ref ERC_TOKEN_TYPE_MAPPING: TypeMapping = IndexMap::from([ - (Name::new("name"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("symbol"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("tokenId"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("decimals"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), - (Name::new("contractAddress"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), + (Name::new("name"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("symbol"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("tokenId"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("decimals"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("contractAddress"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), ]); } diff --git a/crates/torii/graphql/src/object/erc/erc_transfer.rs b/crates/torii/graphql/src/object/erc/erc_transfer.rs index 83bf252b82..16fed939cb 100644 --- a/crates/torii/graphql/src/object/erc/erc_transfer.rs +++ b/crates/torii/graphql/src/object/erc/erc_transfer.rs @@ -79,7 +79,8 @@ SELECT t.name, t.symbol, t.decimals, - c.contract_type + c.contract_type, + et.transaction_hash FROM erc_transfers et JOIN @@ -121,6 +122,7 @@ LIMIT {}; (Name::new("type"), Value::String(row.contract_type)), (Name::new("executedAt"), Value::String(row.executed_at)), (Name::new("tokenMetadata"), token_metadata), + (Name::new("transactionHash"), Value::String(row.transaction_hash.clone())), ])) } "erc721" => { @@ -143,6 +145,7 @@ LIMIT {}; (Name::new("type"), Value::String(row.contract_type)), (Name::new("executedAt"), Value::String(row.executed_at)), (Name::new("tokenMetadata"), token_metadata), + (Name::new("transactionHash"), Value::String(row.transaction_hash.clone())), ])) } _ => { @@ -178,4 +181,5 @@ struct TransferQueryResultRaw { pub symbol: String, pub decimals: u8, pub contract_type: String, + pub transaction_hash: String, } diff --git a/crates/torii/migrations/20241011103804_add_transaction_hash_in_erc_transfers_table.sql b/crates/torii/migrations/20241011103804_add_transaction_hash_in_erc_transfers_table.sql new file mode 100644 index 0000000000..e83643cecb --- /dev/null +++ b/crates/torii/migrations/20241011103804_add_transaction_hash_in_erc_transfers_table.sql @@ -0,0 +1 @@ +ALTER TABLE erc_transfers ADD COLUMN transaction_hash TEXT NOT NULL; \ No newline at end of file