0.7.48
This commit is contained in:
@@ -38,15 +38,10 @@ impl DexEventCoverageService {
|
||||
};
|
||||
}
|
||||
|
||||
/// Synchronizes static upstream registry entries into SQLite coverage rows.
|
||||
///
|
||||
/// The resulting rows are still discovery/audit metadata. A row can become
|
||||
/// observed or materialized only through local corpus replay and explicit
|
||||
/// count refreshes.
|
||||
pub async fn sync_upstream_registry(
|
||||
async fn upsert_upstream_registry_rows(
|
||||
&self,
|
||||
decoder_code: std::option::Option<std::string::String>,
|
||||
) -> Result<crate::DexEventCoverageSyncResult, crate::Error> {
|
||||
) -> Result<(usize, usize), crate::Error> {
|
||||
let request = crate::UpstreamRegistrySearchRequestDto {
|
||||
decoder_code: decoder_code.clone(),
|
||||
program_id: None,
|
||||
@@ -70,6 +65,30 @@ impl DexEventCoverageService {
|
||||
Err(error) => return Err(error),
|
||||
}
|
||||
}
|
||||
return Ok((search_result.entries.len(), upserted_entry_count));
|
||||
}
|
||||
|
||||
async fn ensure_upstream_registry_rows_if_needed(
|
||||
&self,
|
||||
decoder_code: std::option::Option<std::string::String>,
|
||||
) -> Result<(usize, usize), crate::Error> {
|
||||
return self.upsert_upstream_registry_rows(decoder_code).await;
|
||||
}
|
||||
|
||||
/// Synchronizes static upstream registry entries into SQLite coverage rows.
|
||||
///
|
||||
/// The resulting rows are still discovery/audit metadata. A row can become
|
||||
/// observed or materialized only through local corpus replay and explicit
|
||||
/// count refreshes.
|
||||
pub async fn sync_upstream_registry(
|
||||
&self,
|
||||
decoder_code: std::option::Option<std::string::String>,
|
||||
) -> Result<crate::DexEventCoverageSyncResult, crate::Error> {
|
||||
let sync_counts = self.upsert_upstream_registry_rows(decoder_code.clone()).await;
|
||||
let (upstream_entry_count, upserted_entry_count) = match sync_counts {
|
||||
Ok(sync_counts) => sync_counts,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let refreshed_entry_count = match &decoder_code {
|
||||
Some(decoder_code) => {
|
||||
let refresh_result =
|
||||
@@ -103,7 +122,7 @@ impl DexEventCoverageService {
|
||||
};
|
||||
return Ok(crate::DexEventCoverageSyncResult {
|
||||
decoder_code,
|
||||
upstream_entry_count: search_result.entries.len(),
|
||||
upstream_entry_count,
|
||||
upserted_entry_count,
|
||||
refreshed_entry_count,
|
||||
summaries,
|
||||
@@ -115,6 +134,11 @@ impl DexEventCoverageService {
|
||||
&self,
|
||||
decoder_code: std::option::Option<std::string::String>,
|
||||
) -> Result<crate::DexEventCoverageSyncResult, crate::Error> {
|
||||
let sync_counts = self.ensure_upstream_registry_rows_if_needed(decoder_code.clone()).await;
|
||||
let (upstream_entry_count, upserted_entry_count) = match sync_counts {
|
||||
Ok(sync_counts) => sync_counts,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
let refreshed_entry_count = match &decoder_code {
|
||||
Some(decoder_code) => {
|
||||
let refresh_result =
|
||||
@@ -148,8 +172,8 @@ impl DexEventCoverageService {
|
||||
};
|
||||
return Ok(crate::DexEventCoverageSyncResult {
|
||||
decoder_code,
|
||||
upstream_entry_count: 0,
|
||||
upserted_entry_count: 0,
|
||||
upstream_entry_count,
|
||||
upserted_entry_count,
|
||||
refreshed_entry_count,
|
||||
summaries,
|
||||
});
|
||||
@@ -160,8 +184,12 @@ fn build_coverage_entry_from_upstream(
|
||||
entry: &crate::UpstreamRegistryEntryDto,
|
||||
) -> crate::DexEventCoverageEntryDto {
|
||||
let event_family = infer_event_family(entry.entry_name.as_str(), entry.entry_kind.as_str());
|
||||
let expected_db_target =
|
||||
infer_expected_db_target(event_family.as_deref(), entry.entry_kind.as_str());
|
||||
let expected_db_target = infer_expected_db_target_for_entry(
|
||||
entry.decoder_code.as_str(),
|
||||
entry.entry_name.as_str(),
|
||||
event_family.as_deref(),
|
||||
entry.entry_kind.as_str(),
|
||||
);
|
||||
let local_event_kind =
|
||||
known_local_event_kind(entry.decoder_code.as_str(), entry.entry_name.as_str());
|
||||
let mut coverage_entry = crate::DexEventCoverageEntryDto::from_upstream_registry_entry(
|
||||
@@ -177,6 +205,18 @@ fn build_coverage_entry_from_upstream(
|
||||
return coverage_entry;
|
||||
}
|
||||
|
||||
fn infer_expected_db_target_for_entry(
|
||||
decoder_code: &str,
|
||||
entry_name: &str,
|
||||
event_family: std::option::Option<&str>,
|
||||
entry_kind: &str,
|
||||
) -> std::option::Option<std::string::String> {
|
||||
if decoder_code == "raydium_cpmm" && entry_name == "swap_event" {
|
||||
return Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string());
|
||||
}
|
||||
return infer_expected_db_target(event_family, entry_kind);
|
||||
}
|
||||
|
||||
fn infer_expected_db_target(
|
||||
event_family: std::option::Option<&str>,
|
||||
entry_kind: &str,
|
||||
@@ -195,6 +235,7 @@ fn infer_expected_db_target(
|
||||
let target = match family {
|
||||
"swap" => crate::DexEventCoverageEntryDto::DB_TARGET_TRADE_EVENTS,
|
||||
"pool_create" => crate::DexEventCoverageEntryDto::DB_TARGET_POOL_LIFECYCLE_EVENTS,
|
||||
"liquidity" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
|
||||
"liquidity_add" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
|
||||
"liquidity_remove" => crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS,
|
||||
"position_open" => crate::DexEventCoverageEntryDto::DB_TARGET_POOL_LIFECYCLE_EVENTS,
|
||||
@@ -235,6 +276,9 @@ fn infer_event_family(
|
||||
return None;
|
||||
}
|
||||
let normalized = entry_name.to_ascii_lowercase();
|
||||
if normalized == "lp_change_event" {
|
||||
return Some("liquidity".to_string());
|
||||
}
|
||||
if contains_any(normalized.as_str(), &["swap", "buy", "sell", "trade"]) {
|
||||
return Some("swap".to_string());
|
||||
}
|
||||
@@ -360,29 +404,58 @@ fn known_local_event_kind(
|
||||
entry_name: &str,
|
||||
) -> std::option::Option<std::string::String> {
|
||||
match (decoder_code, entry_name) {
|
||||
("raydium-cpmm", "swap_base_input") => {
|
||||
("raydium_cpmm", "swap_base_input") => {
|
||||
return Some("raydium_cpmm.swap_base_input".to_string());
|
||||
},
|
||||
("raydium-cpmm", "swap_base_output") => {
|
||||
("raydium_cpmm", "swap_base_output") => {
|
||||
return Some("raydium_cpmm.swap_base_output".to_string());
|
||||
},
|
||||
("raydium-cpmm", "collect_creator_fee") => {
|
||||
("raydium_cpmm", "close_permission_pda") => {
|
||||
return Some("raydium_cpmm.close_permission_pda".to_string());
|
||||
},
|
||||
("raydium_cpmm", "collect_creator_fee") => {
|
||||
return Some("raydium_cpmm.collect_creator_fee".to_string());
|
||||
},
|
||||
("raydium-cpmm", "withdraw") => return Some("raydium_cpmm.withdraw".to_string()),
|
||||
("raydium-cpmm", "initialize") => return Some("raydium_cpmm.initialize".to_string()),
|
||||
("raydium-clmm", "swap") => return Some("raydium_clmm.swap".to_string()),
|
||||
("raydium-clmm", "swap_v2") => return Some("raydium_clmm.swap_v2".to_string()),
|
||||
("raydium-clmm", "increase_liquidity_v2") => {
|
||||
("raydium_cpmm", "collect_fund_fee") => {
|
||||
return Some("raydium_cpmm.collect_fund_fee".to_string());
|
||||
},
|
||||
("raydium_cpmm", "collect_protocol_fee") => {
|
||||
return Some("raydium_cpmm.collect_protocol_fee".to_string());
|
||||
},
|
||||
("raydium_cpmm", "create_amm_config") => {
|
||||
return Some("raydium_cpmm.create_amm_config".to_string());
|
||||
},
|
||||
("raydium_cpmm", "create_permission_pda") => {
|
||||
return Some("raydium_cpmm.create_permission_pda".to_string());
|
||||
},
|
||||
("raydium_cpmm", "deposit") => return Some("raydium_cpmm.deposit".to_string()),
|
||||
("raydium_cpmm", "initialize") => return Some("raydium_cpmm.initialize".to_string()),
|
||||
("raydium_cpmm", "initialize_with_permission") => {
|
||||
return Some("raydium_cpmm.initialize_with_permission".to_string());
|
||||
},
|
||||
("raydium_cpmm", "lp_change_event") => {
|
||||
return Some("raydium_cpmm.lp_change_event".to_string());
|
||||
},
|
||||
("raydium_cpmm", "swap_event") => return Some("raydium_cpmm.swap_event".to_string()),
|
||||
("raydium_cpmm", "update_amm_config") => {
|
||||
return Some("raydium_cpmm.update_amm_config".to_string());
|
||||
},
|
||||
("raydium_cpmm", "update_pool_status") => {
|
||||
return Some("raydium_cpmm.update_pool_status".to_string());
|
||||
},
|
||||
("raydium_cpmm", "withdraw") => return Some("raydium_cpmm.withdraw".to_string()),
|
||||
("raydium_clmm", "swap") => return Some("raydium_clmm.swap".to_string()),
|
||||
("raydium_clmm", "swap_v2") => return Some("raydium_clmm.swap_v2".to_string()),
|
||||
("raydium_clmm", "increase_liquidity_v2") => {
|
||||
return Some("raydium_clmm.increase_liquidity_v2".to_string());
|
||||
},
|
||||
("raydium-clmm", "decrease_liquidity_v2") => {
|
||||
("raydium_clmm", "decrease_liquidity_v2") => {
|
||||
return Some("raydium_clmm.decrease_liquidity_v2".to_string());
|
||||
},
|
||||
("raydium-clmm", "open_position_with_token22_nft") => {
|
||||
("raydium_clmm", "open_position_with_token22_nft") => {
|
||||
return Some("raydium_clmm.open_position_with_token22_nft".to_string());
|
||||
},
|
||||
("raydium-clmm", "close_position") => {
|
||||
("raydium_clmm", "close_position") => {
|
||||
return Some("raydium_clmm.close_position".to_string());
|
||||
},
|
||||
_ => return None,
|
||||
@@ -442,7 +515,7 @@ mod tests {
|
||||
async fn sync_upstream_registry_persists_raydium_cpmm_coverage_rows() {
|
||||
let database = make_database().await;
|
||||
let service = crate::DexEventCoverageService::new(database.clone());
|
||||
let result = service.sync_upstream_registry(Some("raydium-cpmm".to_string())).await;
|
||||
let result = service.sync_upstream_registry(Some("raydium_cpmm".to_string())).await;
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(error) => panic!("coverage sync must succeed: {}", error),
|
||||
@@ -451,7 +524,7 @@ mod tests {
|
||||
assert_eq!(result.upstream_entry_count, result.upserted_entry_count);
|
||||
let rows_result = crate::query_dex_event_coverage_entries_list_by_decoder(
|
||||
database.as_ref(),
|
||||
"raydium-cpmm",
|
||||
"raydium_cpmm",
|
||||
)
|
||||
.await;
|
||||
let rows = match rows_result {
|
||||
@@ -467,7 +540,46 @@ mod tests {
|
||||
assert!(rows.iter().any(|row| return {
|
||||
row.entry_name == "deposit"
|
||||
&& row.event_family == Some("liquidity_add".to_string())
|
||||
&& row.local_event_kind.is_none()
|
||||
&& row.local_event_kind == Some("raydium_cpmm.deposit".to_string())
|
||||
}));
|
||||
assert!(rows.iter().any(|row| return {
|
||||
row.entry_name == "lp_change_event"
|
||||
&& row.event_family == Some("liquidity".to_string())
|
||||
&& row.expected_db_target
|
||||
== Some(crate::DexEventCoverageEntryDto::DB_TARGET_LIQUIDITY_EVENTS.to_string())
|
||||
&& row.local_event_kind == Some("raydium_cpmm.lp_change_event".to_string())
|
||||
}));
|
||||
assert!(rows.iter().any(|row| return {
|
||||
row.entry_name == "swap_event"
|
||||
&& row.event_family == Some("swap".to_string())
|
||||
&& row.expected_db_target
|
||||
== Some(
|
||||
crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string(),
|
||||
)
|
||||
&& row.local_event_kind == Some("raydium_cpmm.swap_event".to_string())
|
||||
}));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn refresh_local_counts_auto_syncs_empty_coverage_table() {
|
||||
let database = make_database().await;
|
||||
let service = crate::DexEventCoverageService::new(database.clone());
|
||||
let result = service.refresh_local_counts(Some("raydium_cpmm".to_string())).await;
|
||||
let result = match result {
|
||||
Ok(result) => result,
|
||||
Err(error) => panic!("coverage refresh must succeed: {}", error),
|
||||
};
|
||||
assert!(result.upstream_entry_count > 0);
|
||||
assert_eq!(result.upstream_entry_count, result.upserted_entry_count);
|
||||
let rows_result = crate::query_dex_event_coverage_entries_list_by_decoder(
|
||||
database.as_ref(),
|
||||
"raydium_cpmm",
|
||||
)
|
||||
.await;
|
||||
let rows = match rows_result {
|
||||
Ok(rows) => rows,
|
||||
Err(error) => panic!("coverage rows must load: {}", error),
|
||||
};
|
||||
assert!(!rows.is_empty());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user