-
Notifications
You must be signed in to change notification settings - Fork 193
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(torii-indexer): eip 4906 update metadata processor #2984
base: main
Are you sure you want to change the base?
Conversation
WalkthroughOhayo! This pull request introduces a new event processor for handling ERC-4906 metadata updates within the indexer. A new processor file is added with methods for event key generation, validation, task prioritization, unique task identification, and asynchronous processing that updates the database. Additionally, the module declaration is expanded to include this new processor. Separately, the token registration flow in the SQLite executor is refactored by extracting token URI and metadata fetching into dedicated functions and adding a new method for updating ERC-721 metadata. Changes
Sequence Diagram(s)sequenceDiagram
participant E as Event
participant P as Erc4906MetadataUpdateProcessor
participant DB as Database
E->>P: Trigger MetadataUpdate event
P->>P: Validate event structure
P->>P: Generate task identifier & assign priority
P->>DB: Update ERC721 metadata
DB-->>P: Confirmation
P->>P: Log debug message
sequenceDiagram
participant C as Client
participant E as Executor
participant P as Provider
participant DB as Database
C->>E: Register ERC721 token query
E->>P: fetch_token_uri (token id, contract address)
P-->>E: Return Token URI (or empty)
E->>E: Evaluate Token URI
E->>P: fetch_token_metadata (if URI is not empty)
P-->>E: Return Token metadata
E->>DB: update_erc721_metadata (store metadata)
DB-->>E: Confirmation
Possibly Related PRs
Suggested Reviewers
📜 Recent review detailsConfiguration used: .coderabbit.yaml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (2)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (1)
45-66
: Task identifier generation is clear, but watch out for collision risk.
Although aDefaultHasher
is generally fine, collisions can occur. If collisions become problematic, consider using a more robust hashing approach (e.g., SHA-256).crates/torii/sqlite/src/executor/erc.rs (1)
236-265
: Solid metadata fetching error handling.
The fallback to an empty string if an error occurs is user-friendly. Should you need to differentiate partial vs. total failures, consider logging more details or re-trying.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
(1 hunks)crates/torii/indexer/src/processors/mod.rs
(1 hunks)crates/torii/sqlite/src/executor/erc.rs
(4 hunks)
✅ Files skipped from review due to trivial changes (1)
- crates/torii/indexer/src/processors/mod.rs
🔇 Additional comments (6)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (3)
1-11
: Ohayo sensei! Imports look organized and consistent.
No issues found with these initial lines, and all dependencies seem necessary.
18-29
: Good approach on setting the event key.
Returning"MetadataUpdate"
clarifies intent and simplifies subsequent usage. No further adjustments needed.
31-43
: Validation logic looks straightforward.
It properly distinguishes single vs. batch metadata updates by checking the event keys count and data emptiness.crates/torii/sqlite/src/executor/erc.rs (3)
183-234
: Fetching token URI is well-structured, sensei!
The fallback totokenURI
is clever, and the warning for both failures is helpful. Just ensure that the empty string fallback won't cause unexpected behaviors downstream.
267-287
: Metadata update method looks clean.
Storing metadata based on the newly fetched URI is separated nicely. This improves maintainability.
289-313
: Great use of functional decomposition inprocess_register_erc721_token_query
.
The modular approach (fetching separately) streamlines the logic. No major issues here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (7)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (4)
30-42
: Ohayo sensei, consider validating the batch rangeIn the batch update path (
event.keys.len() == 5
), you might want to confirmfrom_token_id <= to_token_id
in thisvalidate
method to avoid silently skipping or handling invalid ranges.🧰 Tools
🪛 GitHub Actions: ci
[warning] 33-33: Line exceeds maximum length. Consider breaking the line for better readability.
48-65
: Ohayo sensei, consider stronger hashingIf collisions for
task_identifier
pose a risk, consider using a more robust cryptographic hash (e.g., SHA256) instead ofDefaultHasher
.🧰 Tools
🪛 GitHub Actions: ci
[warning] 48-48: Line exceeds maximum length. Consider breaking the line for better readability.
67-116
: Ohayo sensei, watch out for large batch loopsIf
to_token_id - from_token_id
is very large, iterating over every token may impact performance. Consider batching or chunk-based database updates.🧰 Tools
🪛 GitHub Actions: ci
[warning] 80-80: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 93-93: Line exceeds maximum length. Consider breaking the line for better readability.
33-33
: Ohayo sensei, break up lines to satisfy pipeline formattingThe pipeline flags lines 33, 48, 80, and 93 for exceeding the recommended maximum length. Consider splitting them for improved readability:
-if event.keys.len() == 3 && event.data.is_empty() { +if event.keys.len() == 3 + && event.data.is_empty() { return true; }(and similarly for lines 48, 80, and 93)
Also applies to: 48-48, 80-80, 93-93
🧰 Tools
🪛 GitHub Actions: ci
[warning] 33-33: Line exceeds maximum length. Consider breaking the line for better readability.
crates/torii/sqlite/src/erc.rs (1)
146-161
: Ohayo sensei, nice straightforward update method
update_erc721_metadata
is concise and effective. A small suggestion: adding logs on success or failure might help with debugging and tracing.crates/torii/sqlite/src/executor/erc.rs (2)
242-271
: Ohayo sensei, graceful error fallbackReturning an empty string if the metadata fetch fails keeps the workflow moving. Optionally, you could log or meter repeated failures to spot systemic issues.
🧰 Tools
🪛 GitHub Actions: ci
[warning] 247-247: Line exceeds maximum length. Consider breaking the line for better readability.
247-247
: Ohayo sensei, friendly reminder about line lengthThe pipeline flagged lines 247, 280, 302, and 309 for exceeding the recommended maximum. Splitting them bolsters clarity.
Also applies to: 280-280, 302-302, 309-309
🧰 Tools
🪛 GitHub Actions: ci
[warning] 247-247: Line exceeds maximum length. Consider breaking the line for better readability.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
(1 hunks)crates/torii/sqlite/src/erc.rs
(2 hunks)crates/torii/sqlite/src/executor/erc.rs
(5 hunks)crates/torii/sqlite/src/executor/mod.rs
(3 hunks)
🧰 Additional context used
🪛 GitHub Actions: ci
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
[warning] 33-33: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 48-48: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 80-80: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 93-93: Line exceeds maximum length. Consider breaking the line for better readability.
crates/torii/sqlite/src/executor/erc.rs
[warning] 247-247: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 280-280: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 302-302: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 309-309: Line exceeds maximum length. Consider breaking the line for better readability.
🔇 Additional comments (7)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (2)
25-28
: Ohayo sensei, looks goodNo issues found with
event_key
—it neatly identifies the MetadataUpdate event for further processing.
44-46
: Ohayo sensei, task_priority seems well-chosenKeeping this processor at a slightly lower priority than transfer tasks sounds logical.
crates/torii/sqlite/src/executor/erc.rs (3)
48-52
: Ohayo sensei, struct definition looks good
UpdateErc721MetadataQuery
cleanly encapsulates the needed fields for metadata updates.
189-240
: Ohayo sensei, dual-entry-point check is smartFalling back from
token_uri
totokenURI
preserves flexibility. The warning and empty value fallback align well with robust error handling.
295-319
: Ohayo sensei, cohesive registration flowThe
process_register_erc721_token_query
neatly pipes throughfetch_token_uri
andfetch_token_metadata
. Implementation looks consistent.🧰 Tools
🪛 GitHub Actions: ci
[warning] 302-302: Line exceeds maximum length. Consider breaking the line for better readability.
[warning] 309-309: Line exceeds maximum length. Consider breaking the line for better readability.
crates/torii/sqlite/src/executor/mod.rs (2)
119-119
: LGTM! Clean enum variant addition.The new
UpdateErc721Metadata
variant is well-named and follows the established pattern.
766-775
: Ohayo! Clean implementation of metadata update handling, sensei!The implementation follows the established patterns with proper logging, error handling, and duration tracking.
pub async fn update_erc721_metadata( | ||
&mut self, | ||
contract_address: Felt, | ||
token_id: U256, | ||
provider: Arc<P>, | ||
) -> Result<()> { | ||
let token_uri = Self::fetch_token_uri(&provider, contract_address, token_id).await?; | ||
let metadata = Self::fetch_token_metadata(contract_address, token_id, &token_uri).await?; | ||
|
||
// Update metadata in database | ||
sqlx::query( | ||
"UPDATE tokens SET metadata = ? WHERE contract_address = ? AND id LIKE ?", | ||
) | ||
.bind(&metadata) | ||
.bind(felt_to_sql_string(&contract_address)) | ||
.bind(format!("%{}", u256_to_sql_string(&token_id))) | ||
.execute(&mut *self.transaction) | ||
.await?; | ||
|
||
Ok(()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ohayo sensei, consider using an exact match instead of LIKE
Using LIKE '%...
may inadvertently update multiple tokens if IDs share a suffix. Switching to an exact match:
- "UPDATE tokens SET metadata = ? WHERE contract_address = ? AND id LIKE ?"
+ "UPDATE tokens SET metadata = ? WHERE contract_address = ? AND id = ?"
...avoids accidental collisions.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
pub async fn update_erc721_metadata( | |
&mut self, | |
contract_address: Felt, | |
token_id: U256, | |
provider: Arc<P>, | |
) -> Result<()> { | |
let token_uri = Self::fetch_token_uri(&provider, contract_address, token_id).await?; | |
let metadata = Self::fetch_token_metadata(contract_address, token_id, &token_uri).await?; | |
// Update metadata in database | |
sqlx::query( | |
"UPDATE tokens SET metadata = ? WHERE contract_address = ? AND id LIKE ?", | |
) | |
.bind(&metadata) | |
.bind(felt_to_sql_string(&contract_address)) | |
.bind(format!("%{}", u256_to_sql_string(&token_id))) | |
.execute(&mut *self.transaction) | |
.await?; | |
Ok(()) | |
} | |
pub async fn update_erc721_metadata( | |
&mut self, | |
contract_address: Felt, | |
token_id: U256, | |
provider: Arc<P>, | |
) -> Result<()> { | |
let token_uri = Self::fetch_token_uri(&provider, contract_address, token_id).await?; | |
let metadata = Self::fetch_token_metadata(contract_address, token_id, &token_uri).await?; | |
// Update metadata in database | |
sqlx::query( | |
"UPDATE tokens SET metadata = ? WHERE contract_address = ? AND id = ?", | |
) | |
.bind(&metadata) | |
.bind(felt_to_sql_string(&contract_address)) | |
.bind(format!("%{}", u256_to_sql_string(&token_id))) | |
.execute(&mut *self.transaction) | |
.await?; | |
Ok(()) | |
} |
🧰 Tools
🪛 GitHub Actions: ci
[warning] 280-280: Line exceeds maximum length. Consider breaking the line for better readability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (1)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (1)
25-43
: Consider using constants for key lengths, sensei!The validation logic is correct but would be more maintainable with named constants instead of magic numbers.
+ const SINGLE_UPDATE_KEY_LENGTH: usize = 3; + const BATCH_UPDATE_KEY_LENGTH: usize = 5; + fn validate(&self, event: &Event) -> bool { // Single token metadata update: [hash(MetadataUpdate), token_id.low, token_id.high] - if event.keys.len() == 3 && event.data.is_empty() { + if event.keys.len() == Self::SINGLE_UPDATE_KEY_LENGTH && event.data.is_empty() { return true; } // Batch metadata update: [hash(BatchMetadataUpdate), from_token_id.low, from_token_id.high, // to_token_id.low, to_token_id.high] - if event.keys.len() == 5 && event.data.is_empty() { + if event.keys.len() == Self::BATCH_UPDATE_KEY_LENGTH && event.data.is_empty() { return true; }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
(1 hunks)crates/torii/indexer/src/processors/mod.rs
(2 hunks)crates/torii/sqlite/src/executor/erc.rs
(5 hunks)crates/torii/sqlite/src/executor/mod.rs
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- crates/torii/indexer/src/processors/mod.rs
- crates/torii/sqlite/src/executor/mod.rs
- crates/torii/sqlite/src/executor/erc.rs
⏰ Context from checks skipped due to timeout of 90000ms (4)
- GitHub Check: ensure-wasm
- GitHub Check: docs
- GitHub Check: clippy
- GitHub Check: build
🔇 Additional comments (3)
crates/torii/indexer/src/processors/erc4906_metadata_update.rs (3)
1-16
: Ohayo sensei! The imports and constants look good!All necessary dependencies are properly imported and the log target is well-defined.
17-18
: The struct declaration is clean and minimal!Good use of
Default
andDebug
derives for this unit struct.
49-64
: Heads up on potential race conditions in batch updates, sensei!While serializing batch updates by contract address prevents overlapping range issues, it might create a bottleneck if multiple non-overlapping ranges could be processed in parallel. Consider if this level of serialization is necessary.
✅ Verification successful
Ohayo, sensei! Let's get a better look at the context within the file to ensure we're making an informed call on potential race conditions. I'm going to grab more lines around the
task_identifier
function incrates/torii/indexer/src/processors/erc4906_metadata_update.rs
for deeper analysis.
Ohayo, sensei! After checking out the code context in
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
, it's clear that the design intentionally hashes only the contract address for batch updates. This ensures that batch updates for the same contract are serialized to prevent race conditions from overlapping token ranges. While this does mean that non-overlapping ranges can't be processed concurrently, the current approach is a deliberate trade-off to maintain safety. No changes are needed unless improved parallelism becomes a priority.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Check if there are any other batch processors that might provide insights rg -A 5 "batch.*process|process.*batch" --type rustLength of output: 53
Script:
#!/bin/bash # Display relevant context around the task_identifier function in the ERC4906 metadata update processor sed -n '40,80p' crates/torii/indexer/src/processors/erc4906_metadata_update.rsLength of output: 1353
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2984 +/- ##
==========================================
- Coverage 56.62% 56.49% -0.14%
==========================================
Files 431 433 +2
Lines 57637 57964 +327
==========================================
+ Hits 32637 32746 +109
- Misses 25000 25218 +218 ☔ View full report in Codecov by Sentry. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (1)
crates/torii/sqlite/src/executor/mod.rs (1)
769-779
: Consider enhancing error handling for metadata updates.The implementation looks good sensei, but consider adding more detailed error handling to provide better diagnostics when metadata updates fail.
QueryType::UpdateErc721Metadata(update_metadata) => { debug!(target: LOG_TARGET, "Updating ERC721 metadata."); let instant = Instant::now(); - self.update_erc721_metadata( - update_metadata.contract_address, - update_metadata.token_id, - self.provider.clone(), - ) - .await?; + match self.update_erc721_metadata( + update_metadata.contract_address, + update_metadata.token_id, + self.provider.clone(), + ).await { + Ok(_) => { + debug!(target: LOG_TARGET, duration = ?instant.elapsed(), "Updated ERC721 metadata."); + } + Err(e) => { + error!( + target: LOG_TARGET, + error = %e, + contract_address = %update_metadata.contract_address, + token_id = %update_metadata.token_id, + "Failed to update ERC721 metadata" + ); + return Err(e); + } + }; - debug!(target: LOG_TARGET, duration = ?instant.elapsed(), "Updated ERC721 metadata."); }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
crates/torii/sqlite/src/executor/erc.rs
(8 hunks)crates/torii/sqlite/src/executor/mod.rs
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- crates/torii/sqlite/src/executor/erc.rs
⏰ Context from checks skipped due to timeout of 90000ms (3)
- GitHub Check: clippy
- GitHub Check: build
- GitHub Check: docs
🔇 Additional comments (2)
crates/torii/sqlite/src/executor/mod.rs (2)
10-10
: LGTM!Ohayo! The import is well-organized with other erc-related imports.
120-120
: LGTM!The new query type follows the established pattern and is well-integrated into the enum.
Summary by CodeRabbit
New Features
Refactor