// 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 { 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::( 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, crate::Error> { if limit == 0 { return Ok(std::vec::Vec::new()); } match database.connection() { crate::DatabaseConnection::Sqlite(pool) => { let query_result = sqlx::query_as::( 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); }, } }