0.7.48-pre
This commit is contained in:
778
kb_lib/src/db/queries/dex_event_coverage_entry.rs
Normal file
778
kb_lib/src/db/queries/dex_event_coverage_entry.rs
Normal file
@@ -0,0 +1,778 @@
|
||||
// file: kb_lib/src/db/queries/dex_event_coverage_entry.rs
|
||||
|
||||
//! Queries for `k_sol_dex_event_coverage_entries`.
|
||||
|
||||
/// Inserts or updates one DEX event coverage entry.
|
||||
pub async fn query_dex_event_coverage_entries_upsert(
|
||||
database: &crate::Database,
|
||||
dto: &crate::DexEventCoverageEntryDto,
|
||||
) -> Result<i64, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
r#"
|
||||
INSERT INTO k_sol_dex_event_coverage_entries (
|
||||
coverage_key,
|
||||
decoder_code,
|
||||
program_id,
|
||||
program_family,
|
||||
surface_kind,
|
||||
source_repo,
|
||||
source_path,
|
||||
entry_kind,
|
||||
entry_name,
|
||||
discriminator_hex,
|
||||
discriminator_len,
|
||||
event_family,
|
||||
expected_db_target,
|
||||
proof_status,
|
||||
local_event_kind,
|
||||
observed_count,
|
||||
materialized_count,
|
||||
trade_count,
|
||||
first_signature,
|
||||
last_signature,
|
||||
notes,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(coverage_key) DO UPDATE SET
|
||||
decoder_code = excluded.decoder_code,
|
||||
program_id = excluded.program_id,
|
||||
program_family = excluded.program_family,
|
||||
surface_kind = excluded.surface_kind,
|
||||
source_repo = excluded.source_repo,
|
||||
source_path = excluded.source_path,
|
||||
entry_kind = excluded.entry_kind,
|
||||
entry_name = excluded.entry_name,
|
||||
discriminator_hex = excluded.discriminator_hex,
|
||||
discriminator_len = excluded.discriminator_len,
|
||||
event_family = excluded.event_family,
|
||||
expected_db_target = excluded.expected_db_target,
|
||||
proof_status = excluded.proof_status,
|
||||
local_event_kind = excluded.local_event_kind,
|
||||
observed_count = excluded.observed_count,
|
||||
materialized_count = excluded.materialized_count,
|
||||
trade_count = excluded.trade_count,
|
||||
first_signature = excluded.first_signature,
|
||||
last_signature = excluded.last_signature,
|
||||
notes = excluded.notes,
|
||||
updated_at = excluded.updated_at
|
||||
"#,
|
||||
)
|
||||
.bind(dto.coverage_key.clone())
|
||||
.bind(dto.decoder_code.clone())
|
||||
.bind(dto.program_id.clone())
|
||||
.bind(dto.program_family.clone())
|
||||
.bind(dto.surface_kind.clone())
|
||||
.bind(dto.source_repo.clone())
|
||||
.bind(dto.source_path.clone())
|
||||
.bind(dto.entry_kind.clone())
|
||||
.bind(dto.entry_name.clone())
|
||||
.bind(dto.discriminator_hex.clone())
|
||||
.bind(dto.discriminator_len)
|
||||
.bind(dto.event_family.clone())
|
||||
.bind(dto.expected_db_target.clone())
|
||||
.bind(dto.proof_status.clone())
|
||||
.bind(dto.local_event_kind.clone())
|
||||
.bind(dto.observed_count)
|
||||
.bind(dto.materialized_count)
|
||||
.bind(dto.trade_count)
|
||||
.bind(dto.first_signature.clone())
|
||||
.bind(dto.last_signature.clone())
|
||||
.bind(dto.notes.clone())
|
||||
.bind(dto.created_at.to_rfc3339())
|
||||
.bind(dto.updated_at.to_rfc3339())
|
||||
.execute(pool)
|
||||
.await;
|
||||
if let Err(error) = query_result {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot upsert k_sol_dex_event_coverage_entries on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
let id_result = sqlx::query_scalar::<sqlx::Sqlite, i64>(
|
||||
r#"
|
||||
SELECT id
|
||||
FROM k_sol_dex_event_coverage_entries
|
||||
WHERE coverage_key = ?
|
||||
LIMIT 1
|
||||
"#,
|
||||
)
|
||||
.bind(dto.coverage_key.clone())
|
||||
.fetch_one(pool)
|
||||
.await;
|
||||
match id_result {
|
||||
Ok(id) => return Ok(id),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot fetch k_sol_dex_event_coverage_entries id for coverage_key '{}' on sqlite: {}",
|
||||
dto.coverage_key, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes all event coverage rows for one decoder.
|
||||
pub async fn query_dex_event_coverage_entries_delete_by_decoder(
|
||||
database: &crate::Database,
|
||||
decoder_code: &str,
|
||||
) -> Result<u64, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_event_coverage_entries
|
||||
WHERE decoder_code = ?
|
||||
"#,
|
||||
)
|
||||
.bind(decoder_code.to_string())
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(query_result) => return Ok(query_result.rows_affected()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete k_sol_dex_event_coverage_entries for decoder_code '{}' on sqlite: {}",
|
||||
decoder_code, error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists event coverage rows for one decoder.
|
||||
pub async fn query_dex_event_coverage_entries_list_by_decoder(
|
||||
database: &crate::Database,
|
||||
decoder_code: &str,
|
||||
) -> Result<std::vec::Vec<crate::DexEventCoverageEntryDto>, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::DexEventCoverageEntryEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
id,
|
||||
coverage_key,
|
||||
decoder_code,
|
||||
program_id,
|
||||
program_family,
|
||||
surface_kind,
|
||||
source_repo,
|
||||
source_path,
|
||||
entry_kind,
|
||||
entry_name,
|
||||
discriminator_hex,
|
||||
discriminator_len,
|
||||
event_family,
|
||||
expected_db_target,
|
||||
proof_status,
|
||||
local_event_kind,
|
||||
observed_count,
|
||||
materialized_count,
|
||||
trade_count,
|
||||
first_signature,
|
||||
last_signature,
|
||||
notes,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM k_sol_dex_event_coverage_entries
|
||||
WHERE decoder_code = ?
|
||||
ORDER BY entry_kind ASC, entry_name ASC, discriminator_hex ASC, id ASC
|
||||
"#,
|
||||
)
|
||||
.bind(decoder_code.to_string())
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot list k_sol_dex_event_coverage_entries for decoder_code '{}' on sqlite: {}",
|
||||
decoder_code, error
|
||||
)));
|
||||
},
|
||||
};
|
||||
return dex_event_coverage_entry_entities_to_dtos(entities);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists event coverage summaries grouped by decoder.
|
||||
pub async fn query_dex_event_coverage_entries_list_summary_by_decoder(
|
||||
database: &crate::Database,
|
||||
) -> Result<std::vec::Vec<crate::DexEventCoverageSummaryDto>, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result =
|
||||
sqlx::query_as::<sqlx::Sqlite, crate::DexEventCoverageSummaryEntity>(
|
||||
r#"
|
||||
SELECT
|
||||
decoder_code,
|
||||
COUNT(*) AS listed_entry_count,
|
||||
SUM(CASE WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 1 ELSE 0 END) AS decoded_entry_count,
|
||||
SUM(CASE WHEN observed_count > 0 THEN 1 ELSE 0 END) AS observed_entry_count,
|
||||
SUM(CASE WHEN materialized_count > 0 THEN 1 ELSE 0 END) AS materialized_entry_count,
|
||||
COALESCE(SUM(observed_count), 0) AS total_observed_count,
|
||||
COALESCE(SUM(materialized_count), 0) AS total_materialized_count,
|
||||
COALESCE(SUM(trade_count), 0) AS trade_count,
|
||||
SUM(CASE WHEN expected_db_target = 'k_sol_dex_decoded_events_only' THEN 1 ELSE 0 END) AS audit_only_entry_count,
|
||||
SUM(CASE WHEN expected_db_target IS NULL OR expected_db_target = '' THEN 1 ELSE 0 END) AS missing_db_target_entry_count,
|
||||
SUM(CASE WHEN proof_status = 'upstream_git_unverified' THEN 1 ELSE 0 END) AS upstream_git_unverified_entry_count,
|
||||
SUM(CASE WHEN proof_status = 'upstream_git_mapped_unverified' THEN 1 ELSE 0 END) AS upstream_git_mapped_unverified_entry_count,
|
||||
SUM(CASE WHEN proof_status = 'upstream_git_local_corpus_observed' THEN 1 ELSE 0 END) AS upstream_git_local_corpus_observed_entry_count,
|
||||
SUM(CASE WHEN proof_status = 'upstream_git_local_corpus_materialized' THEN 1 ELSE 0 END) AS upstream_git_local_corpus_materialized_entry_count
|
||||
FROM k_sol_dex_event_coverage_entries
|
||||
GROUP BY decoder_code
|
||||
ORDER BY decoder_code ASC
|
||||
"#,
|
||||
)
|
||||
.fetch_all(pool)
|
||||
.await;
|
||||
let entities = match query_result {
|
||||
Ok(entities) => entities,
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot list k_sol_dex_event_coverage_entries summaries on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
};
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
let dto_result = crate::DexEventCoverageSummaryDto::try_from(entity);
|
||||
let dto = match dto_result {
|
||||
Ok(dto) => dto,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
return Ok(dtos);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Refreshes local observed/materialized counts for every coverage row.
|
||||
pub async fn query_dex_event_coverage_entries_refresh_local_counts(
|
||||
database: &crate::Database,
|
||||
) -> Result<u64, crate::Error> {
|
||||
return query_dex_event_coverage_entries_refresh_local_counts_internal(database, None).await;
|
||||
}
|
||||
|
||||
/// Refreshes local observed/materialized counts for one decoder coverage subset.
|
||||
pub async fn query_dex_event_coverage_entries_refresh_local_counts_by_decoder(
|
||||
database: &crate::Database,
|
||||
decoder_code: &str,
|
||||
) -> Result<u64, crate::Error> {
|
||||
return query_dex_event_coverage_entries_refresh_local_counts_internal(
|
||||
database,
|
||||
Some(decoder_code),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn query_dex_event_coverage_entries_refresh_local_counts_internal(
|
||||
database: &crate::Database,
|
||||
decoder_code: std::option::Option<&str>,
|
||||
) -> Result<u64, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let now = chrono::Utc::now().to_rfc3339();
|
||||
let decoder_code_filter: std::option::Option<String> = match decoder_code {
|
||||
Some(value) => Some(value.to_string()),
|
||||
None => None,
|
||||
};
|
||||
let update_result = sqlx::query(
|
||||
r#"
|
||||
UPDATE k_sol_dex_event_coverage_entries
|
||||
SET
|
||||
observed_count = (
|
||||
SELECT COUNT(*)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
trade_count = (
|
||||
SELECT COUNT(te.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
),
|
||||
materialized_count = CASE
|
||||
WHEN expected_db_target = 'k_sol_trade_events' THEN (
|
||||
SELECT COUNT(te.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_trade_events te ON te.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
WHEN expected_db_target = 'k_sol_liquidity_events' THEN (
|
||||
SELECT COUNT(le.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_liquidity_events le ON le.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
WHEN expected_db_target = 'k_sol_pool_lifecycle_events' THEN (
|
||||
SELECT COUNT(pe.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_pool_lifecycle_events pe ON pe.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
WHEN expected_db_target = 'k_sol_fee_events' THEN (
|
||||
SELECT COUNT(fe.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_fee_events fe ON fe.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
WHEN expected_db_target = 'k_sol_reward_events' THEN (
|
||||
SELECT COUNT(re.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_reward_events re ON re.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
WHEN expected_db_target = 'k_sol_pool_admin_events' THEN (
|
||||
SELECT COUNT(ae.id)
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_pool_admin_events ae ON ae.decoded_event_id = de.id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
ELSE materialized_count
|
||||
END,
|
||||
first_signature = (
|
||||
SELECT tx.signature
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
ORDER BY COALESCE(tx.slot, 0) ASC, tx.id ASC
|
||||
LIMIT 1
|
||||
),
|
||||
last_signature = (
|
||||
SELECT tx.signature
|
||||
FROM k_sol_dex_decoded_events de
|
||||
JOIN k_sol_chain_transactions tx ON tx.id = de.transaction_id
|
||||
WHERE (
|
||||
(k_sol_dex_event_coverage_entries.program_id IS NULL OR de.program_id = k_sol_dex_event_coverage_entries.program_id)
|
||||
AND (
|
||||
(
|
||||
k_sol_dex_event_coverage_entries.local_event_kind IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.local_event_kind <> ''
|
||||
AND de.event_kind = k_sol_dex_event_coverage_entries.local_event_kind
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.entry_name IS NOT NULL
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamEntryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamInstructionName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.upstreamEventName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
OR json_extract(de.payload_json, '$.entryName') = k_sol_dex_event_coverage_entries.entry_name
|
||||
)
|
||||
)
|
||||
OR (
|
||||
k_sol_dex_event_coverage_entries.discriminator_hex IS NOT NULL
|
||||
AND k_sol_dex_event_coverage_entries.discriminator_hex <> ''
|
||||
AND (
|
||||
json_extract(de.payload_json, '$.upstreamDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.instructionDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.anchorEventDiscriminator') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
OR json_extract(de.payload_json, '$.discriminatorHex') = k_sol_dex_event_coverage_entries.discriminator_hex
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
ORDER BY COALESCE(tx.slot, 0) DESC, tx.id DESC
|
||||
LIMIT 1
|
||||
),
|
||||
updated_at = ?
|
||||
WHERE (? IS NULL OR decoder_code = ?)
|
||||
"#,
|
||||
)
|
||||
.bind(now.clone())
|
||||
.bind(decoder_code_filter.clone())
|
||||
.bind(decoder_code_filter.clone())
|
||||
.execute(pool)
|
||||
.await;
|
||||
let refreshed_entry_count = match update_result {
|
||||
Ok(result) => result.rows_affected(),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot refresh k_sol_dex_event_coverage_entries local counts on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
};
|
||||
let proof_result = sqlx::query(
|
||||
r#"
|
||||
UPDATE k_sol_dex_event_coverage_entries
|
||||
SET
|
||||
proof_status = CASE
|
||||
WHEN materialized_count > 0 OR trade_count > 0 THEN 'upstream_git_local_corpus_materialized'
|
||||
WHEN observed_count > 0 THEN 'upstream_git_local_corpus_observed'
|
||||
WHEN local_event_kind IS NOT NULL AND local_event_kind <> '' THEN 'upstream_git_mapped_unverified'
|
||||
ELSE proof_status
|
||||
END,
|
||||
updated_at = ?
|
||||
WHERE (? IS NULL OR decoder_code = ?)
|
||||
"#,
|
||||
)
|
||||
.bind(now)
|
||||
.bind(decoder_code_filter.clone())
|
||||
.bind(decoder_code_filter)
|
||||
.execute(pool)
|
||||
.await;
|
||||
if let Err(error) = proof_result {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot refresh k_sol_dex_event_coverage_entries proof statuses on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
}
|
||||
return Ok(refreshed_entry_count);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
fn dex_event_coverage_entry_entities_to_dtos(
|
||||
entities: std::vec::Vec<crate::DexEventCoverageEntryEntity>,
|
||||
) -> Result<std::vec::Vec<crate::DexEventCoverageEntryDto>, crate::Error> {
|
||||
let mut dtos = std::vec::Vec::new();
|
||||
for entity in entities {
|
||||
let dto_result = crate::DexEventCoverageEntryDto::try_from(entity);
|
||||
let dto = match dto_result {
|
||||
Ok(dto) => dto,
|
||||
Err(error) => return Err(error),
|
||||
};
|
||||
dtos.push(dto);
|
||||
}
|
||||
return Ok(dtos);
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
async fn make_database() -> crate::Database {
|
||||
let tempdir = tempfile::tempdir().expect("tempdir must succeed");
|
||||
let database_path = tempdir.path().join("dex_event_coverage.sqlite3");
|
||||
let config = crate::DatabaseConfig {
|
||||
enabled: true,
|
||||
backend: crate::DatabaseBackend::Sqlite,
|
||||
sqlite: crate::SqliteDatabaseConfig {
|
||||
path: database_path.to_string_lossy().to_string(),
|
||||
create_if_missing: true,
|
||||
busy_timeout_ms: 5000,
|
||||
max_connections: 1,
|
||||
auto_initialize_schema: true,
|
||||
use_wal: true,
|
||||
},
|
||||
};
|
||||
return crate::Database::connect_and_initialize(&config)
|
||||
.await
|
||||
.expect("database init must succeed");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn dex_event_coverage_entry_roundtrip_and_summary_work() {
|
||||
let database = make_database().await;
|
||||
let upstream_service = crate::UpstreamRegistryService::new();
|
||||
let request = crate::UpstreamRegistrySearchRequestDto {
|
||||
decoder_code: Some("raydium-cpmm".to_string()),
|
||||
program_id: None,
|
||||
program_family: None,
|
||||
surface_kind: None,
|
||||
entry_kind: Some(crate::ENTRY_KIND_INSTRUCTION.to_string()),
|
||||
proof_status: None,
|
||||
limit: Some(1),
|
||||
};
|
||||
let upstream_result = upstream_service.search(&request);
|
||||
assert_eq!(upstream_result.entries.len(), 1);
|
||||
let upstream_entry = upstream_result.entries.first().expect("entry must exist");
|
||||
let mut dto = crate::DexEventCoverageEntryDto::from_upstream_registry_entry(
|
||||
upstream_entry,
|
||||
Some("swap".to_string()),
|
||||
Some(crate::DexEventCoverageEntryDto::DB_TARGET_DECODED_EVENTS_ONLY.to_string()),
|
||||
Some("raydium_cpmm.swap".to_string()),
|
||||
);
|
||||
dto.proof_status = crate::PROOF_STATUS_UPSTREAM_GIT_LOCAL_CORPUS_OBSERVED.to_string();
|
||||
dto.observed_count = 3;
|
||||
let id = crate::query_dex_event_coverage_entries_upsert(&database, &dto)
|
||||
.await
|
||||
.expect("coverage upsert must succeed");
|
||||
assert!(id > 0);
|
||||
let rows =
|
||||
crate::query_dex_event_coverage_entries_list_by_decoder(&database, "raydium-cpmm")
|
||||
.await
|
||||
.expect("coverage list must succeed");
|
||||
assert_eq!(rows.len(), 1);
|
||||
assert_eq!(rows[0].observed_count, 3);
|
||||
let summaries = crate::query_dex_event_coverage_entries_list_summary_by_decoder(&database)
|
||||
.await
|
||||
.expect("coverage summary must succeed");
|
||||
assert_eq!(summaries.len(), 1);
|
||||
assert_eq!(summaries[0].decoder_code, "raydium-cpmm");
|
||||
assert_eq!(summaries[0].listed_entry_count, 1);
|
||||
assert_eq!(summaries[0].decoded_entry_count, 1);
|
||||
assert_eq!(summaries[0].observed_entry_count, 1);
|
||||
assert_eq!(summaries[0].total_observed_count, 3);
|
||||
assert_eq!(summaries[0].audit_only_entry_count, 1);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user