Files
khadhroony-bobobot/kb_lib/src/db/queries/liquidity_event.rs
2026-05-13 20:11:29 +02:00

197 lines
5.9 KiB
Rust

// file: kb_lib/src/db/queries/liquidity_event.rs
//! Queries for `k_sol_liquidity_events`.
/// Inserts or updates one normalized liquidity event row.
pub async fn query_liquidity_events_upsert(
database: &crate::Database,
dto: &crate::LiquidityEventDto,
) -> Result<i64, crate::Error> {
let slot_i64 = match dto.slot {
Some(slot) => {
let slot_result = i64::try_from(slot);
match slot_result {
Ok(slot) => Some(slot),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot convert liquidity event slot '{}' to i64: {}",
slot, error
)));
},
}
},
None => None,
};
match database.connection() {
crate::DatabaseConnection::Sqlite(pool) => {
let query_result = sqlx::query(
r#"
INSERT INTO k_sol_liquidity_events (
transaction_id,
decoded_event_id,
dex_id,
pool_id,
pair_id,
signature,
instruction_index,
slot,
program_id,
event_kind,
event_kind_text,
actor_wallet,
base_token_id,
quote_token_id,
lp_token_id,
base_amount,
quote_amount,
lp_amount,
amounts_are_complete,
payload_json,
executed_at,
created_at
)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(signature, instruction_index) DO UPDATE SET
transaction_id = excluded.transaction_id,
decoded_event_id = excluded.decoded_event_id,
dex_id = excluded.dex_id,
pool_id = excluded.pool_id,
pair_id = excluded.pair_id,
slot = excluded.slot,
program_id = excluded.program_id,
event_kind = excluded.event_kind,
event_kind_text = excluded.event_kind_text,
actor_wallet = excluded.actor_wallet,
base_token_id = excluded.base_token_id,
quote_token_id = excluded.quote_token_id,
lp_token_id = excluded.lp_token_id,
base_amount = excluded.base_amount,
quote_amount = excluded.quote_amount,
lp_amount = excluded.lp_amount,
amounts_are_complete = excluded.amounts_are_complete,
payload_json = excluded.payload_json,
executed_at = excluded.executed_at
"#,
)
.bind(dto.transaction_id)
.bind(dto.decoded_event_id)
.bind(dto.dex_id)
.bind(dto.pool_id)
.bind(dto.pair_id)
.bind(dto.signature.clone())
.bind(dto.instruction_index)
.bind(slot_i64)
.bind(dto.program_id.clone())
.bind(dto.event_kind.to_i16())
.bind(dto.event_kind_text.clone())
.bind(dto.actor_wallet.clone())
.bind(dto.base_token_id)
.bind(dto.quote_token_id)
.bind(dto.lp_token_id)
.bind(dto.base_amount.clone())
.bind(dto.quote_amount.clone())
.bind(dto.lp_amount.clone())
.bind(if dto.amounts_are_complete { 1_i64 } else { 0_i64 })
.bind(dto.payload_json.clone())
.bind(dto.executed_at.to_rfc3339())
.bind(dto.created_at.to_rfc3339())
.execute(pool)
.await;
if let Err(error) = query_result {
return Err(crate::Error::Db(format!(
"cannot upsert k_sol_liquidity_events on sqlite: {}",
error
)));
}
let id_result = sqlx::query_scalar::<sqlx::Sqlite, i64>(
r#"
SELECT id
FROM k_sol_liquidity_events
WHERE signature = ? AND instruction_index = ?
LIMIT 1
"#,
)
.bind(dto.signature.clone())
.bind(dto.instruction_index)
.fetch_one(pool)
.await;
match id_result {
Ok(id) => return Ok(id),
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot fetch k_sol_liquidity_events id for signature '{}' and instruction_index '{}' on sqlite: {}",
dto.signature, dto.instruction_index, error
)));
},
}
},
}
}
/// Lists recent liquidity events ordered from newest to oldest.
pub async fn query_liquidity_events_list_recent(
database: &crate::Database,
limit: u32,
) -> Result<std::vec::Vec<crate::LiquidityEventDto>, crate::Error> {
if limit == 0 {
return Ok(std::vec::Vec::new());
}
match database.connection() {
crate::DatabaseConnection::Sqlite(pool) => {
let query_result = sqlx::query_as::<sqlx::Sqlite, crate::LiquidityEventEntity>(
r#"
SELECT
id,
transaction_id,
decoded_event_id,
dex_id,
pool_id,
pair_id,
signature,
instruction_index,
slot,
program_id,
event_kind,
event_kind_text,
actor_wallet,
base_token_id,
quote_token_id,
lp_token_id,
base_amount,
quote_amount,
lp_amount,
amounts_are_complete,
payload_json,
executed_at,
created_at
FROM k_sol_liquidity_events
ORDER BY id DESC
LIMIT ?
"#,
)
.bind(i64::from(limit))
.fetch_all(pool)
.await;
let entities = match query_result {
Ok(entities) => entities,
Err(error) => {
return Err(crate::Error::Db(format!(
"cannot list k_sol_liquidity_events on sqlite: {}",
error
)));
},
};
let mut dtos = std::vec::Vec::new();
for entity in entities {
let dto_result = crate::LiquidityEventDto::try_from(entity);
let dto = match dto_result {
Ok(dto) => dto,
Err(error) => return Err(error),
};
dtos.push(dto);
}
return Ok(dtos);
},
}
}