From d1cfea41553c9be1592e8aba26adcff000638324 Mon Sep 17 00:00:00 2001 From: Dagur Valberg Johannsson Date: Mon, 2 Feb 2026 11:08:52 +0100 Subject: [PATCH] Don't fetch CRC20 info for tokens that have BCMR When BCMR data exist; we prefer to use it. Thus we don't need to fetch CRC20 data for tokens in this case. --- src/db/crc20/mod.rs | 61 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 60 insertions(+), 1 deletion(-) diff --git a/src/db/crc20/mod.rs b/src/db/crc20/mod.rs index 9445823..1d77942 100644 --- a/src/db/crc20/mod.rs +++ b/src/db/crc20/mod.rs @@ -57,8 +57,17 @@ pub fn insert_crc20_candidate(conn: &Connection, token_id: &TokenID) -> Result<( } pub fn get_not_indexed_tokens(conn: &Connection) -> Result> { + // Skip tokens that already have valid BCMR metadata (entry in bcmr_data table). + // In practice there is little overlap between BCMR and CRC20 tokens, but if + // BCMR metadata exists we prefer it and skip the CRC20 fetch. let mut stmt = conn.prepare( - "SELECT token_id FROM crc20_candidates WHERE is_crc20 = ?1 AND failed_attempts <= ?2", + "SELECT c.token_id + FROM crc20_candidates c + WHERE c.is_crc20 = ?1 + AND c.failed_attempts <= ?2 + AND NOT EXISTS ( + SELECT 1 FROM bcmr_data b WHERE b.token_id = c.token_id + )", )?; let mut rows = stmt.query(params![STATE_NOT_INDEXED, MAX_FAILED_ATTEMPTS])?; @@ -149,3 +158,53 @@ pub fn bump_failed_attempts(conn: &Connection, token_hex: &str) -> Result<()> { Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use bitcoin_hashes::hex::FromHex; + + #[test] + fn test_get_not_indexed_tokens_excludes_bcmr_tokens() { + // Test that tokens with BCMR metadata are excluded from CRC20 fetching + let conn = Connection::open_in_memory().unwrap(); + + // Set up crc20 tables + prepare_tables(&conn); + + // Set up bcmr tables (includes bcmr_data) + crate::db::bcmr::prepare_tables(&conn); + + // Token A: has no BCMR data (should be returned) + let token_a = + TokenID::from_hex("0101010101010101010101010101010101010101010101010101010101010101") + .unwrap(); + // Token B: has BCMR data (should be excluded) + let token_b = + TokenID::from_hex("0202020202020202020202020202020202020202020202020202020202020202") + .unwrap(); + + // Insert both as CRC20 candidates (not indexed state) + insert_crc20_candidate(&conn, &token_a).unwrap(); + insert_crc20_candidate(&conn, &token_b).unwrap(); + + // Insert BCMR data for token B only + let utxo_blob: Vec = vec![0xaa; 32]; + conn.execute( + "INSERT INTO bcmr_data (token_id, utxo, symbol, decimals, name, description, icon, web, expected_hash, actual_hash) + VALUES (?1, ?2, 'TST', 8, 'Test Token', 'A test token', '', '', '', '')", + params![token_b.to_blob(), utxo_blob], + ) + .unwrap(); + + // Get not indexed tokens - should only return token A + let result = get_not_indexed_tokens(&conn).unwrap(); + + assert_eq!(result.len(), 1, "should only return 1 token"); + assert_eq!( + result[0].to_lowercase(), + token_a.to_hex().to_lowercase(), + "should return token_a (without BCMR data)" + ); + } +}