Skip to content
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

Open
wants to merge 9 commits into
base: main
Choose a base branch
from

Conversation

Larkooo
Copy link
Collaborator

@Larkooo Larkooo commented Feb 3, 2025

Summary by CodeRabbit

  • New Features

    • Introduced a new processor for handling ERC-4906 metadata updates, improving the management of token metadata.
    • Added functionality for updating ERC721 metadata in the database, enhancing overall token management capabilities.
  • Refactor

    • Modularized the token registration logic, streamlining the update process and improving error handling for a more robust experience.
    • Enhanced the executor's capabilities to handle updates to ERC721 metadata.

Copy link

coderabbitai bot commented Feb 3, 2025

Walkthrough

Ohayo! 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

File(s) Change Summary
crates/torii/indexer/src/processors/erc4906_metadata_update.rs
crates/torii/indexer/src/processors/mod.rs
Added the Erc4906MetadataUpdateProcessor with methods: event_key, validate, task_priority, task_identifier, and asynchronous process; and declared a new module for ERC-4906 updates.
crates/torii/sqlite/src/executor/erc.rs Refactored ERC721 token registration by replacing logic in process_register_erc721_token_query with new methods: fetch_token_uri, fetch_token_metadata, and update_erc721_metadata to modularize token processing and improve error handling.
crates/torii/sqlite/src/erc.rs Added a new asynchronous method update_erc721_metadata for updating ERC721 metadata in the Sql implementation.
crates/torii/sqlite/src/executor/mod.rs Introduced a new query type UpdateErc721Metadata in the QueryType enum and updated handle_query_message to manage this new query type.

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
Loading
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
Loading

Possibly Related PRs

  • feat(torii-indexer): task manager & parallelize erc transfers #2913: The changes in the main PR, which introduce the Erc4906MetadataUpdateProcessor and its methods, are related to the modifications in the retrieved PR that refactor task management and processing logic, particularly through the use of task_priority and task_identifier methods, which are also implemented in the new processor.

Suggested Reviewers

  • glihm (sensei)

📜 Recent review details

Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9c16fc6 and d9b2762.

📒 Files selected for processing (1)
  • crates/torii/sqlite/src/executor/erc.rs (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • crates/torii/sqlite/src/executor/erc.rs

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a 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 a DefaultHasher 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

📥 Commits

Reviewing files that changed from the base of the PR and between e823d42 and 5a75b26.

📒 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 to tokenURI 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 in process_register_erc721_token_query.
The modular approach (fetching separately) streamlines the logic. No major issues here.

Copy link

@coderabbitai coderabbitai bot left a 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 range

In the batch update path (event.keys.len() == 5), you might want to confirm from_token_id <= to_token_id in this validate 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 hashing

If collisions for task_identifier pose a risk, consider using a more robust cryptographic hash (e.g., SHA256) instead of DefaultHasher.

🧰 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 loops

If 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 formatting

The 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 fallback

Returning 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 length

The 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

📥 Commits

Reviewing files that changed from the base of the PR and between 5a75b26 and 605231f.

📒 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 good

No issues found with event_key—it neatly identifies the MetadataUpdate event for further processing.


44-46: Ohayo sensei, task_priority seems well-chosen

Keeping 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 smart

Falling back from token_uri to tokenURI preserves flexibility. The warning and empty value fallback align well with robust error handling.


295-319: Ohayo sensei, cohesive registration flow

The process_register_erc721_token_query neatly pipes through fetch_token_uri and fetch_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.

Comment on lines 273 to 293
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(())
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

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.

Suggested change
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.

Copy link

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between 605231f and 036f04b.

📒 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 and Debug 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 in crates/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 rust

Length 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.rs

Length of output: 1353

Copy link

codecov bot commented Feb 3, 2025

Codecov Report

Attention: Patch coverage is 0% with 153 lines in your changes missing coverage. Please review.

Project coverage is 56.49%. Comparing base (b8e5ebb) to head (d9b2762).
Report is 4 commits behind head on main.

Files with missing lines Patch % Lines
crates/torii/sqlite/src/executor/erc.rs 0.00% 61 Missing ⚠️
.../indexer/src/processors/erc4906_metadata_update.rs 0.00% 59 Missing ⚠️
crates/torii/sqlite/src/erc.rs 0.00% 23 Missing ⚠️
crates/torii/sqlite/src/executor/mod.rs 0.00% 10 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

Copy link

@coderabbitai coderabbitai bot left a 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

📥 Commits

Reviewing files that changed from the base of the PR and between 18c0083 and fc928bd.

📒 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant