From d1c7629bfca07f2e9bdb3f1eda113bd02243528b Mon Sep 17 00:00:00 2001 From: lambda-0x <0xlambda@protonmail.com> Date: Thu, 28 Nov 2024 14:48:09 +0530 Subject: [PATCH] fix(torii): handle case where token_id no longer exists and few graphql changes commit-id:e92e39b0 --- crates/torii/core/src/executor/erc.rs | 86 +++++++++++++------ crates/torii/graphql/src/mapping.rs | 12 +-- .../graphql/src/object/erc/token_balance.rs | 12 ++- .../graphql/src/object/erc/token_transfer.rs | 12 ++- 4 files changed, 85 insertions(+), 37 deletions(-) diff --git a/crates/torii/core/src/executor/erc.rs b/crates/torii/core/src/executor/erc.rs index afa39c89c0..a7d91e478a 100644 --- a/crates/torii/core/src/executor/erc.rs +++ b/crates/torii/core/src/executor/erc.rs @@ -10,7 +10,7 @@ use starknet::core::types::{BlockId, BlockTag, FunctionCall, U256}; use starknet::core::utils::{get_selector_from_name, parse_cairo_short_string}; use starknet::providers::Provider; use starknet_crypto::Felt; -use tracing::{debug, trace}; +use tracing::{debug, error, trace}; use super::{ApplyBalanceDiffQuery, Executor}; use crate::constants::{IPFS_CLIENT_MAX_RETRY, SQL_FELT_DELIMITER, TOKEN_BALANCE_TABLE}; @@ -30,7 +30,7 @@ pub struct RegisterErc721TokenMetadata { pub query: RegisterErc721TokenQuery, pub name: String, pub symbol: String, - pub metadata: String, + pub metadata: Option, } #[derive(Debug, Clone)] @@ -159,7 +159,7 @@ impl<'c, P: Provider + Sync + Send + 'static> Executor<'c, P> { ) .await { - token_uri + Some(token_uri) } else if let Ok(token_uri) = provider .call( FunctionCall { @@ -174,32 +174,68 @@ impl<'c, P: Provider + Sync + Send + 'static> Executor<'c, P> { ) .await { - token_uri + Some(token_uri) } else { - return Err(anyhow::anyhow!("Failed to fetch token_uri")); + error!( + "Failed to fetch token_uri for token_id: {}", + register_erc721_token.actual_token_id + ); + None }; - let token_uri = if let Ok(byte_array) = ByteArray::cairo_deserialize(&token_uri, 0) { - byte_array.to_string().expect("Return value not String") - } else if let Ok(felt_array) = Vec::::cairo_deserialize(&token_uri, 0) { - felt_array - .iter() - .map(parse_cairo_short_string) - .collect::, _>>() - .map(|strings| strings.join("")) - .map_err(|_| anyhow::anyhow!("Failed parsing Array to String"))? - } else { - return Err(anyhow::anyhow!("token_uri is neither ByteArray nor Array")); - }; + if let Some(token_uri) = token_uri { + let token_uri = if let Ok(byte_array) = ByteArray::cairo_deserialize(&token_uri, 0) { + Some(byte_array.to_string().expect("Return value not String")) + } else if let Ok(felt_array) = Vec::::cairo_deserialize(&token_uri, 0) { + Some( + felt_array + .iter() + .map(parse_cairo_short_string) + .collect::, _>>() + .map(|strings| strings.join("")) + .map_err(|_| anyhow::anyhow!("Failed parsing Array to String"))?, + ) + } else { + error!( + "token_uri is neither ByteArray nor Array for token_id: {}", + register_erc721_token.actual_token_id + ); + None + }; + + let metadata = if let Some(token_uri) = token_uri { + match Self::fetch_metadata(&token_uri).await { + Ok(metadata) => { + let metadata = serde_json::to_string(&metadata) + .context("Failed to serialize metadata")?; + Some(metadata) + } + Err(e) => { + error!( + "Failed to fetch metadata for token_id: {}, error: {}", + register_erc721_token.actual_token_id, e + ); + None + } + } + } else { + None + }; + + return Ok(RegisterErc721TokenMetadata { + query: register_erc721_token, + metadata, + name, + symbol, + }); + } - let metadata = Self::fetch_metadata(&token_uri).await.with_context(|| { - format!( - "Failed to fetch metadata for token_id: {}", - register_erc721_token.actual_token_id - ) - })?; - let metadata = serde_json::to_string(&metadata).context("Failed to serialize metadata")?; - Ok(RegisterErc721TokenMetadata { query: register_erc721_token, metadata, name, symbol }) + Ok(RegisterErc721TokenMetadata { + query: register_erc721_token, + metadata: None, + name, + symbol, + }) } // given a uri which can be either http/https url or data uri, fetch the metadata erc721 diff --git a/crates/torii/graphql/src/mapping.rs b/crates/torii/graphql/src/mapping.rs index 190cbf4b62..02bbd5618d 100644 --- a/crates/torii/graphql/src/mapping.rs +++ b/crates/torii/graphql/src/mapping.rs @@ -100,8 +100,8 @@ lazy_static! { ), ]); pub static ref PAGE_INFO_TYPE_MAPPING: TypeMapping = TypeMapping::from([ - (Name::new("hasPreviousPage"), TypeData::Simple(TypeRef::named(TypeRef::BOOLEAN))), - (Name::new("hasNextPage"), TypeData::Simple(TypeRef::named(TypeRef::BOOLEAN))), + (Name::new("hasPreviousPage"), TypeData::Simple(TypeRef::named_nn(TypeRef::BOOLEAN))), + (Name::new("hasNextPage"), TypeData::Simple(TypeRef::named_nn(TypeRef::BOOLEAN))), ( Name::new("startCursor"), TypeData::Simple(TypeRef::named(GraphqlType::Cursor.to_string())), @@ -160,7 +160,7 @@ lazy_static! { pub static ref ERC20_TOKEN_TYPE_MAPPING: TypeMapping = IndexMap::from([ (Name::new("name"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), (Name::new("symbol"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), - (Name::new("decimals"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("decimals"), TypeData::Simple(TypeRef::named_nn(TypeRef::INT))), (Name::new("contractAddress"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), (Name::new("amount"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), ]); @@ -171,9 +171,9 @@ lazy_static! { (Name::new("tokenId"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), (Name::new("contractAddress"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), (Name::new("metadata"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), - (Name::new("metadataName"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), - (Name::new("metadataDescription"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), - (Name::new("metadataAttributes"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), + (Name::new("metadataName"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), + (Name::new("metadataDescription"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), + (Name::new("metadataAttributes"), TypeData::Simple(TypeRef::named(TypeRef::STRING))), (Name::new("imagePath"), TypeData::Simple(TypeRef::named_nn(TypeRef::STRING))), ]); diff --git a/crates/torii/graphql/src/object/erc/token_balance.rs b/crates/torii/graphql/src/object/erc/token_balance.rs index 7fdcca4fe5..ab018822e2 100644 --- a/crates/torii/graphql/src/object/erc/token_balance.rs +++ b/crates/torii/graphql/src/object/erc/token_balance.rs @@ -234,8 +234,14 @@ fn token_balances_connection_output<'a>( let token_id = row.token_id.split(':').collect::>(); assert!(token_id.len() == 2); + // skip the token if metadata is null + if row.metadata.is_none() { + continue; + } + let metadata_str = row.metadata.as_ref().unwrap(); + let metadata: serde_json::Value = - serde_json::from_str(&row.metadata).expect("metadata is always json"); + serde_json::from_str(metadata_str).expect("metadata is always json"); let metadata_name = metadata.get("name").map(|v| v.to_string().trim_matches('"').to_string()); let metadata_description = metadata @@ -248,7 +254,7 @@ fn token_balances_connection_output<'a>( let token_metadata = Erc721Token { name: row.name, - metadata: row.metadata, + metadata: metadata_str.to_owned(), contract_address: row.contract_address, symbol: row.symbol, token_id: token_id[1].to_string(), @@ -295,5 +301,5 @@ struct BalanceQueryResultRaw { pub token_id: String, pub balance: String, pub contract_type: String, - pub metadata: String, + pub metadata: Option, } diff --git a/crates/torii/graphql/src/object/erc/token_transfer.rs b/crates/torii/graphql/src/object/erc/token_transfer.rs index 1441937c2e..0053db28dc 100644 --- a/crates/torii/graphql/src/object/erc/token_transfer.rs +++ b/crates/torii/graphql/src/object/erc/token_transfer.rs @@ -263,8 +263,14 @@ fn token_transfers_connection_output<'a>( let token_id = row.token_id.split(':').collect::>(); assert!(token_id.len() == 2); + // skip the token if metadata is null + if row.metadata.is_none() { + continue; + } + + let metadata_str = row.metadata.as_ref().unwrap(); let metadata: serde_json::Value = - serde_json::from_str(&row.metadata).expect("metadata is always json"); + serde_json::from_str(metadata_str).expect("metadata is always json"); let metadata_name = metadata.get("name").map(|v| v.to_string().trim_matches('"').to_string()); let metadata_description = metadata @@ -277,7 +283,7 @@ fn token_transfers_connection_output<'a>( let token_metadata = ErcTokenType::Erc721(Erc721Token { name: row.name, - metadata: row.metadata, + metadata: metadata_str.to_owned(), contract_address: row.contract_address, symbol: row.symbol, token_id: token_id[1].to_string(), @@ -333,7 +339,7 @@ struct TransferQueryResultRaw { pub symbol: String, pub decimals: u8, pub contract_type: String, - pub metadata: String, + pub metadata: Option, } #[derive(Debug, Clone)]