Skip to content

Commit 15a3a3d

Browse files
authored
feat(static): get first token image if no contract img (#398)
* feat(static): get first token image if no contract img * fmt * fix; static
1 parent da591ba commit 15a3a3d

File tree

1 file changed

+98
-4
lines changed

1 file changed

+98
-4
lines changed

crates/server/src/handlers/static.rs

Lines changed: 98 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,36 @@ impl StaticHandler {
377377
Ok(query_result.0)
378378
}
379379

380+
async fn get_first_token_metadata(
381+
&self,
382+
contract_address: &str,
383+
) -> Result<(serde_json::Value, String)> {
384+
// Find tokens with this contract address that have non-empty metadata
385+
let pattern = format!("{}:%", contract_address);
386+
let query_str = format!(
387+
"SELECT metadata, id FROM {TOKENS_TABLE} WHERE id LIKE ? AND metadata != '' ORDER BY id LIMIT 100"
388+
);
389+
let query_results = sqlx::query_as::<_, (String, String)>(&query_str)
390+
.bind(&pattern)
391+
.fetch_all(&self.pool)
392+
.await
393+
.context("Failed to find any tokens for contract address")?;
394+
395+
// Try to find a token with valid metadata that contains an image field
396+
for (metadata_str, token_id) in query_results {
397+
if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&metadata_str) {
398+
if metadata.get("image").is_some() {
399+
return Ok((metadata, token_id));
400+
}
401+
}
402+
}
403+
404+
Err(anyhow::anyhow!(
405+
"No tokens found with valid image metadata for contract address: {}",
406+
contract_address
407+
))
408+
}
409+
380410
async fn check_if_image_outdated(
381411
&self,
382412
token_image_dir: &Utf8PathBuf,
@@ -506,16 +536,80 @@ impl StaticHandler {
506536
token_id: &str,
507537
db_timestamp: Option<&str>,
508538
) -> anyhow::Result<String> {
539+
let is_contract = !token_id.contains(':');
540+
509541
// For both tokens and contracts, we can use the same query since contract address is the ID for contracts
510542
let query_str = format!("SELECT metadata FROM {TOKENS_TABLE} WHERE id = ?");
511543
let query_result = sqlx::query_as::<_, (String,)>(&query_str)
512544
.bind(token_id)
513545
.fetch_one(&self.pool)
514-
.await
515-
.context("Failed to fetch metadata from database")?;
546+
.await;
547+
548+
// Try to get metadata and image_uri, with fallback for contracts
549+
let metadata = match query_result {
550+
Ok(result) => {
551+
// Check if metadata is empty or whitespace-only
552+
let metadata_str = result.0.trim();
553+
if metadata_str.is_empty() {
554+
if is_contract {
555+
// Fallback: try to find first token with this contract address
556+
debug!(target: LOG_TARGET, contract_address = %token_id, "Empty metadata for contract, searching for first token");
557+
let (fallback_metadata, fallback_token_id) =
558+
self.get_first_token_metadata(token_id).await?;
559+
debug!(target: LOG_TARGET, contract_address = %token_id, fallback_token = %fallback_token_id, "Using fallback token image");
560+
fallback_metadata
561+
} else {
562+
return Err(anyhow::anyhow!("Empty metadata for token"));
563+
}
564+
} else {
565+
// Try to parse the metadata
566+
match serde_json::from_str::<serde_json::Value>(metadata_str) {
567+
Ok(metadata) => {
568+
// Check if image field exists
569+
if metadata.get("image").is_some() {
570+
metadata
571+
} else if is_contract {
572+
// Fallback: try to find first token with this contract address
573+
debug!(target: LOG_TARGET, contract_address = %token_id, "No image found in contract metadata, searching for first token");
574+
let (fallback_metadata, fallback_token_id) =
575+
self.get_first_token_metadata(token_id).await?;
576+
debug!(target: LOG_TARGET, contract_address = %token_id, fallback_token = %fallback_token_id, "Using fallback token image");
577+
fallback_metadata
578+
} else {
579+
return Err(anyhow::anyhow!("Image URL not found in metadata"));
580+
}
581+
}
582+
Err(e) => {
583+
if is_contract {
584+
// Fallback: try to find first token with this contract address
585+
debug!(target: LOG_TARGET, contract_address = %token_id, error = ?e, "Failed to parse contract metadata, searching for first token");
586+
let (fallback_metadata, fallback_token_id) =
587+
self.get_first_token_metadata(token_id).await?;
588+
debug!(target: LOG_TARGET, contract_address = %token_id, fallback_token = %fallback_token_id, "Using fallback token image");
589+
fallback_metadata
590+
} else {
591+
return Err(anyhow::anyhow!("Failed to parse metadata: {}", e));
592+
}
593+
}
594+
}
595+
}
596+
}
597+
Err(_) if is_contract => {
598+
// Fallback: try to find first token with this contract address
599+
debug!(target: LOG_TARGET, contract_address = %token_id, "Contract metadata not found, searching for first token");
600+
let (fallback_metadata, fallback_token_id) =
601+
self.get_first_token_metadata(token_id).await?;
602+
debug!(target: LOG_TARGET, contract_address = %token_id, fallback_token = %fallback_token_id, "Using fallback token image");
603+
fallback_metadata
604+
}
605+
Err(e) => {
606+
return Err(anyhow::anyhow!(
607+
"Failed to fetch metadata from database: {}",
608+
e
609+
));
610+
}
611+
};
516612

517-
let metadata: serde_json::Value =
518-
serde_json::from_str(&query_result.0).context("Failed to parse metadata")?;
519613
let image_uri = metadata
520614
.get("image")
521615
.context("Image URL not found in metadata")?

0 commit comments

Comments
 (0)