0.7.45
This commit is contained in:
@@ -128,6 +128,109 @@ WHERE transaction_id = ?
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes decoded DEX instruction audit rows related to one decoded instruction.
|
||||
///
|
||||
/// This removes an audit row attached to the decoded instruction itself, its direct
|
||||
/// parent instruction, or its direct child instructions inside the same transaction.
|
||||
pub async fn query_dex_decoded_events_delete_related_instruction_audit(
|
||||
database: &crate::Database,
|
||||
transaction_id: i64,
|
||||
instruction_id: i64,
|
||||
audit_event_kind: &str,
|
||||
) -> Result<u64, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND event_kind = ?
|
||||
AND instruction_id IN (
|
||||
SELECT id
|
||||
FROM k_sol_chain_instructions
|
||||
WHERE transaction_id = ?
|
||||
AND id = ?
|
||||
|
||||
UNION
|
||||
|
||||
SELECT parent_instruction_id
|
||||
FROM k_sol_chain_instructions
|
||||
WHERE transaction_id = ?
|
||||
AND id = ?
|
||||
AND parent_instruction_id IS NOT NULL
|
||||
|
||||
UNION
|
||||
|
||||
SELECT id
|
||||
FROM k_sol_chain_instructions
|
||||
WHERE transaction_id = ?
|
||||
AND parent_instruction_id = ?
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.bind(audit_event_kind)
|
||||
.bind(transaction_id)
|
||||
.bind(instruction_id)
|
||||
.bind(transaction_id)
|
||||
.bind(instruction_id)
|
||||
.bind(transaction_id)
|
||||
.bind(instruction_id)
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(result) => return Ok(result.rows_affected()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete related instruction audit events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Deletes Meteora DLMM Anchor self-CPI swap audit rows already covered by decoded swaps.
|
||||
///
|
||||
/// This targets only local-corpus-observed Anchor event discriminators that are
|
||||
/// decoded into `meteora_dlmm.swap` payload enrichment. It does not delete
|
||||
/// unrelated DLMM instruction audits.
|
||||
pub async fn query_dex_decoded_events_delete_meteora_dlmm_anchor_swap_instruction_audits(
|
||||
database: &crate::Database,
|
||||
transaction_id: i64,
|
||||
) -> Result<u64, crate::Error> {
|
||||
match database.connection() {
|
||||
crate::DatabaseConnection::Sqlite(pool) => {
|
||||
let query_result = sqlx::query(
|
||||
r#"
|
||||
DELETE FROM k_sol_dex_decoded_events
|
||||
WHERE transaction_id = ?
|
||||
AND protocol_name = 'meteora_dlmm'
|
||||
AND event_kind = 'meteora_dlmm.instruction_audit'
|
||||
AND json_extract(payload_json, '$.anchorSelfCpiLog') = 1
|
||||
AND json_extract(payload_json, '$.anchorEventDiscriminatorHex') IN (
|
||||
'516ce3becdd00ac4',
|
||||
'2e7452d7941b544d'
|
||||
)
|
||||
"#,
|
||||
)
|
||||
.bind(transaction_id)
|
||||
.execute(pool)
|
||||
.await;
|
||||
match query_result {
|
||||
Ok(result) => return Ok(result.rows_affected()),
|
||||
Err(error) => {
|
||||
return Err(crate::Error::Db(format!(
|
||||
"cannot delete Meteora DLMM Anchor swap audit events on sqlite: {}",
|
||||
error
|
||||
)));
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
/// Reads one decoded DEX event by its natural key.
|
||||
pub async fn query_dex_decoded_events_get_by_key(
|
||||
database: &crate::Database,
|
||||
@@ -400,4 +503,106 @@ mod tests {
|
||||
assert_eq!(listed.len(), 1);
|
||||
assert_eq!(listed[0].event_kind, "raydium_amm_v4.initialize2_pool");
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn related_instruction_audit_delete_removes_parent_audit_for_child_decode() {
|
||||
let database = make_database().await;
|
||||
let transaction_dto = crate::ChainTransactionDto::new(
|
||||
"sig-dex-event-related-audit-test-1".to_string(),
|
||||
None,
|
||||
None,
|
||||
Some("helius_primary_http".to_string()),
|
||||
Some("0".to_string()),
|
||||
None,
|
||||
None,
|
||||
r#"{"transaction":{"message":{"instructions":[]}}}"#.to_string(),
|
||||
);
|
||||
let transaction_id_result =
|
||||
crate::query_chain_transactions_upsert(&database, &transaction_dto).await;
|
||||
let transaction_id = match transaction_id_result {
|
||||
Ok(transaction_id) => transaction_id,
|
||||
Err(error) => panic!("transaction upsert must succeed: {}", error),
|
||||
};
|
||||
let parent_instruction_dto = crate::ChainInstructionDto::new(
|
||||
transaction_id,
|
||||
None,
|
||||
0,
|
||||
None,
|
||||
Some(crate::METEORA_DLMM_PROGRAM_ID.to_string()),
|
||||
Some("meteora-dlmm".to_string()),
|
||||
Some(1),
|
||||
r#"["ParentAccount","Pool111"]"#.to_string(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let parent_instruction_id_result =
|
||||
crate::query_chain_instructions_insert(&database, &parent_instruction_dto).await;
|
||||
let parent_instruction_id = match parent_instruction_id_result {
|
||||
Ok(parent_instruction_id) => parent_instruction_id,
|
||||
Err(error) => panic!("parent instruction insert must succeed: {}", error),
|
||||
};
|
||||
let child_instruction_dto = crate::ChainInstructionDto::new(
|
||||
transaction_id,
|
||||
Some(parent_instruction_id),
|
||||
0,
|
||||
Some(0),
|
||||
Some(crate::METEORA_DLMM_PROGRAM_ID.to_string()),
|
||||
Some("meteora-dlmm".to_string()),
|
||||
Some(2),
|
||||
r#"["ChildAccount","Pool111"]"#.to_string(),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
);
|
||||
let child_instruction_id_result =
|
||||
crate::query_chain_instructions_insert(&database, &child_instruction_dto).await;
|
||||
let child_instruction_id = match child_instruction_id_result {
|
||||
Ok(child_instruction_id) => child_instruction_id,
|
||||
Err(error) => panic!("child instruction insert must succeed: {}", error),
|
||||
};
|
||||
let audit_dto = crate::DexDecodedEventDto::new(
|
||||
transaction_id,
|
||||
Some(parent_instruction_id),
|
||||
"meteora_dlmm".to_string(),
|
||||
crate::METEORA_DLMM_PROGRAM_ID.to_string(),
|
||||
"meteora_dlmm.instruction_audit".to_string(),
|
||||
Some("Pool111".to_string()),
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
r#"{"audit":true}"#.to_string(),
|
||||
);
|
||||
let audit_upsert_result =
|
||||
crate::query_dex_decoded_events_upsert(&database, &audit_dto).await;
|
||||
match audit_upsert_result {
|
||||
Ok(_) => {},
|
||||
Err(error) => panic!("audit upsert must succeed: {}", error),
|
||||
}
|
||||
let deleted_result = super::query_dex_decoded_events_delete_related_instruction_audit(
|
||||
&database,
|
||||
transaction_id,
|
||||
child_instruction_id,
|
||||
"meteora_dlmm.instruction_audit",
|
||||
)
|
||||
.await;
|
||||
let deleted = match deleted_result {
|
||||
Ok(deleted) => deleted,
|
||||
Err(error) => panic!("related audit delete must succeed: {}", error),
|
||||
};
|
||||
assert_eq!(deleted, 1);
|
||||
let fetched_result = crate::query_dex_decoded_events_get_by_key(
|
||||
&database,
|
||||
transaction_id,
|
||||
Some(parent_instruction_id),
|
||||
"meteora_dlmm.instruction_audit",
|
||||
)
|
||||
.await;
|
||||
let fetched = match fetched_result {
|
||||
Ok(fetched) => fetched,
|
||||
Err(error) => panic!("audit fetch must succeed: {}", error),
|
||||
};
|
||||
assert!(fetched.is_none());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user